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

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

Issue 11315018: Extensions Docs Server: Generalize $ref's to work for any schema node (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed comments Created 8 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 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 import copy 5 import copy
6 import json 6 import json
7 import logging
7 import os 8 import os
8 9
9 from docs_server_utils import GetLinkToRefType
10 import compiled_file_system as compiled_fs 10 import compiled_file_system as compiled_fs
11 from file_system import FileNotFoundError 11 from file_system import FileNotFoundError
12 from reference_resolver import ReferenceResolver
12 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater 13 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater
13 import third_party.json_schema_compiler.model as model 14 import third_party.json_schema_compiler.model as model
14 import third_party.json_schema_compiler.idl_schema as idl_schema 15 import third_party.json_schema_compiler.idl_schema as idl_schema
15 import third_party.json_schema_compiler.idl_parser as idl_parser 16 import third_party.json_schema_compiler.idl_parser as idl_parser
16 17
17 # Increment this version when there are changes to the data stored in any of 18 # Increment this version when there are changes to the data stored in any of
18 # the caches used by APIDataSource. This allows the cache to be invalidated 19 # the caches used by APIDataSource. This allows the cache to be invalidated
19 # without having to flush memcache on the production server. 20 # without having to flush memcache on the production server.
20 _VERSION = 2 21 _VERSION = 3
21 22
22 def _RemoveNoDocs(item): 23 def _RemoveNoDocs(item):
23 if type(item) == dict: 24 if type(item) == dict:
24 if item.get('nodoc', False): 25 if item.get('nodoc', False):
25 return True 26 return True
26 to_remove = [] 27 to_remove = []
27 for key, value in item.items(): 28 for key, value in item.items():
28 if _RemoveNoDocs(value): 29 if _RemoveNoDocs(value):
29 to_remove.append(key) 30 to_remove.append(key)
30 for k in to_remove: 31 for k in to_remove:
(...skipping 11 matching lines...) Expand all
42 if node.parent is not None and not isinstance(node.parent, model.Namespace): 43 if node.parent is not None and not isinstance(node.parent, model.Namespace):
43 return '-'.join([prefix, node.parent.simple_name, node.simple_name]) 44 return '-'.join([prefix, node.parent.simple_name, node.simple_name])
44 return '-'.join([prefix, node.simple_name]) 45 return '-'.join([prefix, node.simple_name])
45 46
46 def _FormatValue(value): 47 def _FormatValue(value):
47 """Inserts commas every three digits for integer values. It is magic. 48 """Inserts commas every three digits for integer values. It is magic.
48 """ 49 """
49 s = str(value) 50 s = str(value)
50 return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1]) 51 return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1])
51 52
52 class _JscModel(object): 53 class _JSCModel(object):
53 """Uses a Model from the JSON Schema Compiler and generates a dict that 54 """Uses a Model from the JSON Schema Compiler and generates a dict that
54 a Handlebar template can use for a data source. 55 a Handlebar template can use for a data source.
55 """ 56 """
56 def __init__(self, json): 57 def __init__(self, json):
57 clean_json = copy.deepcopy(json) 58 clean_json = copy.deepcopy(json)
58 if _RemoveNoDocs(clean_json): 59 if _RemoveNoDocs(clean_json):
59 self._namespace = None 60 self._namespace = None
60 else: 61 else:
61 self._namespace = model.Namespace(clean_json, clean_json['namespace']) 62 self._namespace = model.Namespace(clean_json, clean_json['namespace'])
62 63
63 def _FormatDescription(self, description): 64 def _GetLinkToRefType(self, ref, ref_resolver):
not at google - send to devlin 2012/11/02 17:26:48 Rename method similar to rename suggestion in Refe
cduvall 2012/11/03 01:30:05 Done.
64 if description is None or '$ref:' not in description: 65 ref_data = ref_resolver.GetLinkToRefType(self._namespace.name, ref)
66 if ref_data is None:
not at google - send to devlin 2012/11/02 17:26:48 nit: invert condition.
cduvall 2012/11/03 01:30:05 Done.
67 logging.error('$ref %s could not be resolved.' % ref)
68 if '.' in ref:
69 type_name = ref.rsplit('.', 1)[-1]
70 else:
71 type_name = ref
72 return { 'href': '#type-%s' % type_name, 'text': ref }
73 return ref_data
74
75 def _FormatDescription(self, description, ref_resolver):
76 if (description is None or
77 '$ref:' not in description or
78 ref_resolver is None):
65 return description 79 return description
66 refs = description.split('$ref:') 80 refs = description.split('$ref:')
67 formatted_description = [refs[0]] 81 formatted_description = [refs[0]]
68 for ref in refs[1:]: 82 for ref in refs[1:]:
69 parts = ref.split(' ', 1) 83 parts = ref.split(' ', 1)
70 if len(parts) == 1: 84 if len(parts) == 1:
71 ref = parts[0] 85 ref = parts[0]
72 rest = '' 86 rest = ''
73 else: 87 else:
74 ref, rest = parts 88 ref, rest = parts
75 rest = ' ' + rest 89 rest = ' ' + rest
76 if not ref[-1].isalnum(): 90 if not ref[-1].isalnum():
77 rest = ref[-1] + rest 91 rest = ref[-1] + rest
78 ref = ref[:-1] 92 ref = ref[:-1]
79 ref_dict = GetLinkToRefType(self._namespace.name, ref) 93 ref_dict = self._GetLinkToRefType(ref, ref_resolver)
80 formatted_description.append('<a href="%(href)s">%(text)s</a>%(rest)s' % 94 formatted_description.append('<a href="%(href)s">%(text)s</a>%(rest)s' %
81 { 'href': ref_dict['href'], 'text': ref_dict['text'], 'rest': rest }) 95 { 'href': ref_dict['href'], 'text': ref_dict['text'], 'rest': rest })
82 return ''.join(formatted_description) 96 return ''.join(formatted_description)
83 97
84 def ToDict(self): 98 def ToDict(self, ref_resolver):
not at google - send to devlin 2012/11/02 17:26:48 Consider introducing a DictBuilder class that is c
cduvall 2012/11/03 01:30:05 I redid JSCModel so that it acts as a DictBuilder.
85 if self._namespace is None: 99 if self._namespace is None:
86 return {} 100 return {}
87 return { 101 return {
88 'name': self._namespace.name, 102 'name': self._namespace.name,
89 'types': [self._GenerateType(t) for t in self._namespace.types.values() 103 'types': [self._GenerateType(t, ref_resolver)
104 for t in self._namespace.types.values()
90 if t.type_ != model.PropertyType.ADDITIONAL_PROPERTIES], 105 if t.type_ != model.PropertyType.ADDITIONAL_PROPERTIES],
91 'functions': self._GenerateFunctions(self._namespace.functions), 106 'functions': self._GenerateFunctions(self._namespace.functions,
92 'events': self._GenerateEvents(self._namespace.events), 107 ref_resolver),
93 'properties': self._GenerateProperties(self._namespace.properties) 108 'events': self._GenerateEvents(self._namespace.events,
109 ref_resolver),
110 'properties': self._GenerateProperties(self._namespace.properties,
111 ref_resolver)
94 } 112 }
95 113
96 def _GenerateType(self, type_): 114 def _GenerateType(self, type_, ref_resolver):
97 type_dict = { 115 type_dict = {
98 'name': type_.simple_name, 116 'name': type_.simple_name,
99 'description': self._FormatDescription(type_.description), 117 'description': self._FormatDescription(type_.description, ref_resolver),
100 'properties': self._GenerateProperties(type_.properties), 118 'properties': self._GenerateProperties(type_.properties, ref_resolver),
101 'functions': self._GenerateFunctions(type_.functions), 119 'functions': self._GenerateFunctions(type_.functions, ref_resolver),
102 'events': self._GenerateEvents(type_.events), 120 'events': self._GenerateEvents(type_.events, ref_resolver),
103 'id': _CreateId(type_, 'type') 121 'id': _CreateId(type_, 'type')
104 } 122 }
105 self._RenderTypeInformation(type_, type_dict) 123 self._RenderTypeInformation(type_, type_dict, ref_resolver)
106 return type_dict 124 return type_dict
107 125
108 def _GenerateFunctions(self, functions): 126 def _GenerateFunctions(self, functions, ref_resolver):
109 return [self._GenerateFunction(f) for f in functions.values()] 127 return [self._GenerateFunction(f, ref_resolver) for f in functions.values()]
110 128
111 def _GenerateFunction(self, function): 129 def _GenerateFunction(self, function, ref_resolver):
112 function_dict = { 130 function_dict = {
113 'name': function.simple_name, 131 'name': function.simple_name,
114 'description': self._FormatDescription(function.description), 132 'description': self._FormatDescription(function.description,
115 'callback': self._GenerateCallback(function.callback), 133 ref_resolver),
134 'callback': self._GenerateCallback(function.callback, ref_resolver),
116 'parameters': [], 135 'parameters': [],
117 'returns': None, 136 'returns': None,
118 'id': _CreateId(function, 'method') 137 'id': _CreateId(function, 'method')
119 } 138 }
120 if (function.parent is not None and 139 if (function.parent is not None and
121 not isinstance(function.parent, model.Namespace)): 140 not isinstance(function.parent, model.Namespace)):
122 function_dict['parent_name'] = function.parent.simple_name 141 function_dict['parent_name'] = function.parent.simple_name
123 else: 142 else:
124 function_dict['parent_name'] = None 143 function_dict['parent_name'] = None
125 if function.returns: 144 if function.returns:
126 function_dict['returns'] = self._GenerateProperty(function.returns) 145 function_dict['returns'] = self._GenerateProperty(function.returns,
146 ref_resolver)
127 for param in function.params: 147 for param in function.params:
128 function_dict['parameters'].append(self._GenerateProperty(param)) 148 function_dict['parameters'].append(self._GenerateProperty(param,
149 ref_resolver))
129 if function_dict['callback']: 150 if function_dict['callback']:
130 function_dict['parameters'].append(function_dict['callback']) 151 function_dict['parameters'].append(function_dict['callback'])
131 if len(function_dict['parameters']) > 0: 152 if len(function_dict['parameters']) > 0:
132 function_dict['parameters'][-1]['last'] = True 153 function_dict['parameters'][-1]['last'] = True
133 return function_dict 154 return function_dict
134 155
135 def _GenerateEvents(self, events): 156 def _GenerateEvents(self, events, ref_resolver):
136 return [self._GenerateEvent(e) for e in events.values()] 157 return [self._GenerateEvent(e, ref_resolver) for e in events.values()]
137 158
138 def _GenerateEvent(self, event): 159 def _GenerateEvent(self, event, ref_resolver):
139 event_dict = { 160 event_dict = {
140 'name': event.simple_name, 161 'name': event.simple_name,
141 'description': self._FormatDescription(event.description), 162 'description': self._FormatDescription(event.description,
142 'parameters': map(self._GenerateProperty, event.params), 163 ref_resolver),
143 'callback': self._GenerateCallback(event.callback), 164 'parameters': [self._GenerateProperty(p, ref_resolver)
144 'conditions': [GetLinkToRefType(self._namespace.name, c) 165 for p in event.params],
145 for c in event.conditions], 166 'callback': self._GenerateCallback(event.callback, ref_resolver),
146 'actions': [GetLinkToRefType(self._namespace.name, a) 167 'filters': [self._GenerateProperty(f, ref_resolver)
147 for a in event.actions], 168 for f in event.filters],
148 'filters': map(self._GenerateProperty, event.filters),
149 'supportsRules': event.supports_rules, 169 'supportsRules': event.supports_rules,
150 'id': _CreateId(event, 'event') 170 'id': _CreateId(event, 'event')
151 } 171 }
172 if ref_resolver is not None:
173 event_dict['conditions'] = [self._GetLinkToRefType(condition,
174 ref_resolver)
175 for condition in event.conditions]
176 event_dict['actions'] = [self._GetLinkToRefType(action, ref_resolver)
177 for action in event.actions]
152 if (event.parent is not None and 178 if (event.parent is not None and
153 not isinstance(event.parent, model.Namespace)): 179 not isinstance(event.parent, model.Namespace)):
154 event_dict['parent_name'] = event.parent.simple_name 180 event_dict['parent_name'] = event.parent.simple_name
155 else: 181 else:
156 event_dict['parent_name'] = None 182 event_dict['parent_name'] = None
157 if event_dict['callback']: 183 if event_dict['callback']:
158 event_dict['parameters'].append(event_dict['callback']) 184 event_dict['parameters'].append(event_dict['callback'])
159 if len(event_dict['parameters']) > 0: 185 if len(event_dict['parameters']) > 0:
160 event_dict['parameters'][-1]['last'] = True 186 event_dict['parameters'][-1]['last'] = True
161 return event_dict 187 return event_dict
162 188
163 def _GenerateCallback(self, callback): 189 def _GenerateCallback(self, callback, ref_resolver):
164 if not callback: 190 if not callback:
165 return None 191 return None
166 callback_dict = { 192 callback_dict = {
167 'name': callback.simple_name, 193 'name': callback.simple_name,
168 'description': self._FormatDescription(callback.description), 194 'description': self._FormatDescription(callback.description,
195 ref_resolver),
169 'simple_type': {'simple_type': 'function'}, 196 'simple_type': {'simple_type': 'function'},
170 'optional': callback.optional, 197 'optional': callback.optional,
171 'parameters': [] 198 'parameters': []
172 } 199 }
173 for param in callback.params: 200 for param in callback.params:
174 callback_dict['parameters'].append(self._GenerateProperty(param)) 201 callback_dict['parameters'].append(
202 self._GenerateProperty(param, ref_resolver))
175 if (len(callback_dict['parameters']) > 0): 203 if (len(callback_dict['parameters']) > 0):
176 callback_dict['parameters'][-1]['last'] = True 204 callback_dict['parameters'][-1]['last'] = True
177 return callback_dict 205 return callback_dict
178 206
179 def _GenerateProperties(self, properties): 207 def _GenerateProperties(self, properties, ref_resolver):
180 return [self._GenerateProperty(v) for v in properties.values() 208 return [self._GenerateProperty(v, ref_resolver) for v in properties.values()
181 if v.type_ != model.PropertyType.ADDITIONAL_PROPERTIES] 209 if v.type_ != model.PropertyType.ADDITIONAL_PROPERTIES]
182 210
183 def _GenerateProperty(self, property_): 211 def _GenerateProperty(self, property_, ref_resolver):
184 property_dict = { 212 property_dict = {
185 'name': property_.simple_name, 213 'name': property_.simple_name,
186 'optional': property_.optional, 214 'optional': property_.optional,
187 'description': self._FormatDescription(property_.description), 215 'description': self._FormatDescription(property_.description,
188 'properties': self._GenerateProperties(property_.properties), 216 ref_resolver),
217 'properties': self._GenerateProperties(property_.properties,
218 ref_resolver),
219 'functions': self._GenerateFunctions(property_.functions, ref_resolver),
189 'parameters': [], 220 'parameters': [],
190 'functions': self._GenerateFunctions(property_.functions),
191 'returns': None, 221 'returns': None,
192 'id': _CreateId(property_, 'property') 222 'id': _CreateId(property_, 'property')
193 } 223 }
194 for param in property_.params: 224 for param in property_.params:
195 property_dict['parameters'].append(self._GenerateProperty(param)) 225 property_dict['parameters'].append(self._GenerateProperty(param,
226 ref_resolver))
196 if property_.returns: 227 if property_.returns:
197 property_dict['returns'] = self._GenerateProperty(property_.returns) 228 property_dict['returns'] = self._GenerateProperty(property_.returns)
198 if (property_.parent is not None and 229 if (property_.parent is not None and
199 not isinstance(property_.parent, model.Namespace)): 230 not isinstance(property_.parent, model.Namespace)):
200 property_dict['parent_name'] = property_.parent.simple_name 231 property_dict['parent_name'] = property_.parent.simple_name
201 else: 232 else:
202 property_dict['parent_name'] = None 233 property_dict['parent_name'] = None
203 if property_.has_value: 234 if property_.has_value:
204 if isinstance(property_.value, int): 235 if isinstance(property_.value, int):
205 property_dict['value'] = _FormatValue(property_.value) 236 property_dict['value'] = _FormatValue(property_.value)
206 else: 237 else:
207 property_dict['value'] = property_.value 238 property_dict['value'] = property_.value
208 else: 239 else:
209 self._RenderTypeInformation(property_, property_dict) 240 self._RenderTypeInformation(property_, property_dict, ref_resolver)
210 return property_dict 241 return property_dict
211 242
212 def _RenderTypeInformation(self, property_, dst_dict): 243 def _RenderTypeInformation(self, property_, dst_dict, ref_resolver):
213 if property_.type_ == model.PropertyType.CHOICES: 244 if property_.type_ == model.PropertyType.CHOICES:
214 dst_dict['choices'] = map(self._GenerateProperty, 245 dst_dict['choices'] = [self._GenerateProperty(c, ref_resolver)
215 property_.choices.values()) 246 for c in property_.choices.values()]
216 # We keep track of which is last for knowing when to add "or" between 247 # We keep track of which is last for knowing when to add "or" between
217 # choices in templates. 248 # choices in templates.
218 if len(dst_dict['choices']) > 0: 249 if len(dst_dict['choices']) > 0:
219 dst_dict['choices'][-1]['last'] = True 250 dst_dict['choices'][-1]['last'] = True
220 elif property_.type_ == model.PropertyType.REF: 251 elif property_.type_ == model.PropertyType.REF:
221 dst_dict['link'] = GetLinkToRefType(self._namespace.name, 252 if ref_resolver is not None:
222 property_.ref_type) 253 dst_dict['link'] = self._GetLinkToRefType(property_.ref_type,
254 ref_resolver)
223 elif property_.type_ == model.PropertyType.ARRAY: 255 elif property_.type_ == model.PropertyType.ARRAY:
224 dst_dict['array'] = self._GenerateProperty(property_.item_type) 256 dst_dict['array'] = self._GenerateProperty(property_.item_type,
257 ref_resolver)
225 elif property_.type_ == model.PropertyType.ENUM: 258 elif property_.type_ == model.PropertyType.ENUM:
226 dst_dict['enum_values'] = [] 259 dst_dict['enum_values'] = []
227 for enum_value in property_.enum_values: 260 for enum_value in property_.enum_values:
228 dst_dict['enum_values'].append({'name': enum_value}) 261 dst_dict['enum_values'].append({'name': enum_value})
229 if len(dst_dict['enum_values']) > 0: 262 if len(dst_dict['enum_values']) > 0:
230 dst_dict['enum_values'][-1]['last'] = True 263 dst_dict['enum_values'][-1]['last'] = True
231 elif property_.instance_of is not None: 264 elif property_.instance_of is not None:
232 dst_dict['simple_type'] = property_.instance_of.lower() 265 dst_dict['simple_type'] = property_.instance_of.lower()
233 else: 266 else:
234 dst_dict['simple_type'] = property_.type_.name.lower() 267 dst_dict['simple_type'] = property_.type_.name.lower()
235 268
236 class _LazySamplesGetter(object): 269 class _LazySamplesGetter(object):
237 """This class is needed so that an extensions API page does not have to fetch 270 """This class is needed so that an extensions API page does not have to fetch
238 the apps samples page and vice versa. 271 the apps samples page and vice versa.
239 """ 272 """
240 def __init__(self, api_name, samples): 273 def __init__(self, api_name, samples):
241 self._api_name = api_name 274 self._api_name = api_name
242 self._samples = samples 275 self._samples = samples
243 276
244 def get(self, key): 277 def get(self, key):
245 return self._samples.FilterSamples(key, self._api_name) 278 return self._samples.FilterSamples(key, self._api_name)
246 279
247 class APIDataSource(object): 280 class APIDataSource(object):
248 """This class fetches and loads JSON APIs from the FileSystem passed in with 281 """This class fetches and loads JSON APIs from the FileSystem passed in with
249 |cache_factory|, so the APIs can be plugged into templates. 282 |cache_factory|, so the APIs can be plugged into templates.
250 """ 283 """
251 class Factory(object): 284 class Factory(object):
252 def __init__(self, cache_factory, base_path, samples_factory): 285 def __init__(self,
286 cache_factory,
287 base_path,
288 api_list_data_source):
not at google - send to devlin 2012/11/02 17:26:48 As I mentioned in handler, should be passing the f
cduvall 2012/11/03 01:30:05 Done.
253 self._permissions_cache = cache_factory.Create(self._LoadPermissions, 289 self._permissions_cache = cache_factory.Create(self._LoadPermissions,
254 compiled_fs.PERMS, 290 compiled_fs.PERMS,
255 version=_VERSION) 291 version=_VERSION)
256 self._json_cache = cache_factory.Create(self._LoadJsonAPI, 292 self._json_cache = cache_factory.Create(self._LoadJsonAPI,
257 compiled_fs.JSON, 293 compiled_fs.JSON,
258 version=_VERSION) 294 version=_VERSION)
259 self._idl_cache = cache_factory.Create(self._LoadIdlAPI, 295 self._idl_cache = cache_factory.Create(self._LoadIdlAPI,
260 compiled_fs.IDL, 296 compiled_fs.IDL,
261 version=_VERSION) 297 version=_VERSION)
262 self._idl_names_cache = cache_factory.Create(self._GetIDLNames, 298 self._idl_names_cache = cache_factory.Create(self._GetIDLNames,
263 compiled_fs.IDL_NAMES, 299 compiled_fs.IDL_NAMES,
264 version=_VERSION) 300 version=_VERSION)
265 self._samples_factory = samples_factory 301 self._names_cache = cache_factory.Create(self._GetAllNames,
302 compiled_fs.NAMES,
303 version=_VERSION)
266 self._base_path = base_path 304 self._base_path = base_path
305 self._ref_resolver = ReferenceResolver(
306 self.Create(None, None, resolve_refs=False),
307 api_list_data_source)
267 308
268 def Create(self, request): 309 def Create(self, request, samples_data_source, resolve_refs=True):
not at google - send to devlin 2012/11/02 17:26:48 It's nice for optional arguments to be False by de
not at google - send to devlin 2012/11/02 17:26:48 Having a separate SetSamplesDataSourceFactory meth
cduvall 2012/11/03 01:30:05 Done.
cduvall 2012/11/03 01:30:05 Done.
310 """Create an APIDataSource. |resolve_refs| specifies whether $ref's in
311 APIs being processed by the |ToDict| method of _JSCModel follows $ref's
312 in the API. This prevents endless recursion in ReferenceResolver.
313 """
269 return APIDataSource(self._permissions_cache, 314 return APIDataSource(self._permissions_cache,
270 self._json_cache, 315 self._json_cache,
271 self._idl_cache, 316 self._idl_cache,
317 self._names_cache,
272 self._idl_names_cache, 318 self._idl_names_cache,
273 self._base_path, 319 self._base_path,
274 self._samples_factory.Create(request)) 320 samples_data_source,
321 self._ref_resolver if resolve_refs else None)
not at google - send to devlin 2012/11/02 17:26:48 nit: push this logic into where ToDict is called (
cduvall 2012/11/03 01:30:05 Done.
275 322
276 def _LoadPermissions(self, json_str): 323 def _LoadPermissions(self, json_str):
277 return json.loads(json_comment_eater.Nom(json_str)) 324 return json.loads(json_comment_eater.Nom(json_str))
278 325
279 def _LoadJsonAPI(self, api): 326 def _LoadJsonAPI(self, api):
280 return _JscModel(json.loads(json_comment_eater.Nom(api))[0]) 327 return _JSCModel(json.loads(json_comment_eater.Nom(api))[0])
281 328
282 def _LoadIdlAPI(self, api): 329 def _LoadIdlAPI(self, api):
283 idl = idl_parser.IDLParser().ParseData(api) 330 idl = idl_parser.IDLParser().ParseData(api)
284 return _JscModel(idl_schema.IDLSchema(idl).process()[0]) 331 return _JSCModel(idl_schema.IDLSchema(idl).process()[0])
285 332
286 def _GetIDLNames(self, apis): 333 def _GetIDLNames(self, apis):
287 return [model.UnixName(os.path.splitext(api.split('/')[-1])[0]) 334 return [
288 for api in apis if api.endswith('.idl')] 335 model.UnixName(os.path.splitext(api[len('%s/' % self._base_path):])[0])
336 for api in apis if api.endswith('.idl')
337 ]
338
339 def _GetAllNames(self, apis):
340 return [
341 model.UnixName(os.path.splitext(api[len('%s/' % self._base_path):])[0])
342 for api in apis
343 ]
289 344
290 def __init__(self, 345 def __init__(self,
291 permissions_cache, 346 permissions_cache,
292 json_cache, 347 json_cache,
293 idl_cache, 348 idl_cache,
349 names_cache,
294 idl_names_cache, 350 idl_names_cache,
295 base_path, 351 base_path,
296 samples): 352 samples,
353 ref_resolver):
297 self._base_path = base_path 354 self._base_path = base_path
298 self._permissions_cache = permissions_cache 355 self._permissions_cache = permissions_cache
299 self._json_cache = json_cache 356 self._json_cache = json_cache
300 self._idl_cache = idl_cache 357 self._idl_cache = idl_cache
358 self._names_cache = names_cache
301 self._idl_names_cache = idl_names_cache 359 self._idl_names_cache = idl_names_cache
302 self._samples = samples 360 self._samples = samples
361 self._ref_resolver = ref_resolver
303 362
304 def _GetPermsFromFile(self, filename): 363 def _GetPermsFromFile(self, filename):
305 try: 364 try:
306 perms = self._permissions_cache.GetFromFile('%s/%s' % 365 perms = self._permissions_cache.GetFromFile('%s/%s' %
307 (self._base_path, filename)) 366 (self._base_path, filename))
308 return dict((model.UnixName(k), v) for k, v in perms.iteritems()) 367 return dict((model.UnixName(k), v) for k, v in perms.iteritems())
309 except FileNotFoundError: 368 except FileNotFoundError:
310 return {} 369 return {}
311 370
312 def _GetFeature(self, path): 371 def _GetFeature(self, path):
313 # Remove 'experimental_' from path name to match the keys in 372 # Remove 'experimental_' from path name to match the keys in
314 # _permissions_features.json. 373 # _permissions_features.json.
315 path = model.UnixName(path.replace('experimental_', '')) 374 path = model.UnixName(path.replace('experimental_', ''))
316 for filename in ['_permission_features.json', '_manifest_features.json']: 375 for filename in ['_permission_features.json', '_manifest_features.json']:
317 api_perms = self._GetPermsFromFile(filename).get(path, None) 376 api_perms = self._GetPermsFromFile(filename).get(path, None)
318 if api_perms is not None: 377 if api_perms is not None:
319 break 378 break
320 if api_perms and api_perms['channel'] in ('trunk', 'dev', 'beta'): 379 if api_perms and api_perms['channel'] in ('trunk', 'dev', 'beta'):
321 api_perms[api_perms['channel']] = True 380 api_perms[api_perms['channel']] = True
322 return api_perms 381 return api_perms
323 382
324 def _GenerateHandlebarContext(self, handlebar, path): 383 def _GenerateHandlebarContext(self, handlebar, path):
325 return_dict = { 384 return_dict = {
326 'permissions': self._GetFeature(path), 385 'permissions': self._GetFeature(path),
327 'samples': _LazySamplesGetter(path, self._samples) 386 'samples': _LazySamplesGetter(path, self._samples)
328 } 387 }
329 return_dict.update(handlebar.ToDict()) 388 return_dict.update(handlebar.ToDict(self._ref_resolver))
330 return return_dict 389 return return_dict
331 390
391 def _GetAsSubdirectory(self, name):
392 if name.startswith('experimental_'):
393 parts = name[len('experimental_'):].split('_', 1)
394 parts[1] = 'experimental_%s' % parts[1]
395 return '/'.join(parts)
396 return name.replace('_', '/', 1)
397
332 def __getitem__(self, key): 398 def __getitem__(self, key):
333 return self.get(key) 399 return self.get(key)
334 400
335 def get(self, key): 401 def get(self, key):
336 path, ext = os.path.splitext(key) 402 if key.endswith('.html') or key.endswith('.json') or key.endswith('.idl'):
403 path, ext = os.path.splitext(key)
404 else:
405 path = key
337 unix_name = model.UnixName(path) 406 unix_name = model.UnixName(path)
338 idl_names = self._idl_names_cache.GetFromFileListing(self._base_path) 407 idl_names = self._idl_names_cache.GetFromFileListing(self._base_path)
408 names = self._names_cache.GetFromFileListing(self._base_path)
409 if unix_name not in names and self._GetAsSubdirectory(unix_name) in names:
410 unix_name = self._GetAsSubdirectory(unix_name)
411
339 cache, ext = ((self._idl_cache, '.idl') if (unix_name in idl_names) else 412 cache, ext = ((self._idl_cache, '.idl') if (unix_name in idl_names) else
340 (self._json_cache, '.json')) 413 (self._json_cache, '.json'))
341 return self._GenerateHandlebarContext( 414 return self._GenerateHandlebarContext(
342 cache.GetFromFile('%s/%s%s' % (self._base_path, unix_name, ext)), 415 cache.GetFromFile('%s/%s%s' % (self._base_path, unix_name, ext)),
343 path) 416 path)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698