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

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

Issue 354073004: Docserver: Add template support for object level availability (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 5 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
« no previous file with comments | « no previous file | chrome/common/extensions/docs/server2/api_data_source_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 from copy import copy 5 from copy import copy
6 import logging 6 import logging
7 import os 7 import os
8 import posixpath 8 import posixpath
9 9
10 from data_source import DataSource 10 from data_source import DataSource
11 from docs_server_utils import StringIdentity 11 from docs_server_utils import StringIdentity
12 from environment import IsPreviewServer 12 from environment import IsPreviewServer
13 from extensions_paths import JSON_TEMPLATES, PRIVATE_TEMPLATES 13 from extensions_paths import JSON_TEMPLATES, PRIVATE_TEMPLATES
14 from file_system import FileNotFoundError 14 from file_system import FileNotFoundError
15 from future import Future, Collect 15 from future import Future, Collect
16 from platform_util import GetPlatforms 16 from platform_util import GetPlatforms
17 import third_party.json_schema_compiler.json_parse as json_parse 17 import third_party.json_schema_compiler.json_parse as json_parse
18 import third_party.json_schema_compiler.model as model 18 import third_party.json_schema_compiler.model as model
19 from environment import IsPreviewServer 19 from environment import IsPreviewServer
20 from third_party.json_schema_compiler.memoize import memoize 20 from third_party.json_schema_compiler.memoize import memoize
21 21
22 22
23 # The set of possible categories a node may belong to.
24 _NODE_CATEGORIES = ('types', 'functions', 'events', 'properties')
25
26
23 def _CreateId(node, prefix): 27 def _CreateId(node, prefix):
24 if node.parent is not None and not isinstance(node.parent, model.Namespace): 28 if node.parent is not None and not isinstance(node.parent, model.Namespace):
25 return '-'.join([prefix, node.parent.simple_name, node.simple_name]) 29 return '-'.join([prefix, node.parent.simple_name, node.simple_name])
26 return '-'.join([prefix, node.simple_name]) 30 return '-'.join([prefix, node.simple_name])
27 31
28 32
29 def _FormatValue(value): 33 def _FormatValue(value):
30 '''Inserts commas every three digits for integer values. It is magic. 34 '''Inserts commas every three digits for integer values. It is magic.
31 ''' 35 '''
32 s = str(value) 36 s = str(value)
33 return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1]) 37 return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1])
34 38
35 39
36 def _GetByNameDict(namespace): 40 def _GetByNameDict(namespace):
37 '''Returns a dictionary mapping names to named items from |namespace|. 41 '''Returns a dictionary mapping names to named items from |namespace|.
38 42
39 This lets us render specific API entities rather than the whole thing at once, 43 This lets us render specific API entities rather than the whole thing at once,
40 for example {{apis.manifestTypes.byName.ExternallyConnectable}}. 44 for example {{apis.manifestTypes.byName.ExternallyConnectable}}.
41 45
42 Includes items from namespace['types'], namespace['functions'], 46 Includes items from namespace['types'], namespace['functions'],
43 namespace['events'], and namespace['properties']. 47 namespace['events'], and namespace['properties'].
44 ''' 48 '''
45 by_name = {} 49 by_name = {}
46 for item_type in ('types', 'functions', 'events', 'properties'): 50 for item_type in _NODE_CATEGORIES:
47 if item_type in namespace: 51 if item_type in namespace:
48 old_size = len(by_name) 52 old_size = len(by_name)
49 by_name.update( 53 by_name.update(
50 (item['name'], item) for item in namespace[item_type]) 54 (item['name'], item) for item in namespace[item_type])
51 assert len(by_name) == old_size + len(namespace[item_type]), ( 55 assert len(by_name) == old_size + len(namespace[item_type]), (
52 'Duplicate name in %r' % namespace) 56 'Duplicate name in %r' % namespace)
53 return by_name 57 return by_name
54 58
55 59
56 def _GetEventByNameFromEvents(events): 60 def _GetEventByNameFromEvents(events):
57 '''Parses the dictionary |events| to find the definitions of members of the 61 '''Parses the dictionary |events| to find the definitions of members of the
58 type Event. Returns a dictionary mapping the name of a member to that 62 type Event. Returns a dictionary mapping the name of a member to that
59 member's definition. 63 member's definition.
60 ''' 64 '''
61 assert 'types' in events, \ 65 assert 'types' in events, \
62 'The dictionary |events| must contain the key "types".' 66 'The dictionary |events| must contain the key "types".'
63 event_list = [t for t in events['types'] if t.get('name') == 'Event'] 67 event_list = [t for t in events['types'] if t.get('name') == 'Event']
64 assert len(event_list) == 1, 'Exactly one type must be called "Event".' 68 assert len(event_list) == 1, 'Exactly one type must be called "Event".'
65 return _GetByNameDict(event_list[0]) 69 return _GetByNameDict(event_list[0])
66 70
67 71
72 class _APINodeCursor(object):
73 '''An abstract representation of a node in an APISchemaGraph.
74 The current position in the graph is represented by a path into the
75 underlying dictionary. So if the APISchemaGraph is:
76
77 {
78 'tabs': {
79 'types': {
80 'Tab': {
81 'properties': {
82 'url': {
83 ...
84 }
85 }
86 }
87 }
88 }
89 }
90
91 then the 'url' property would be represented by:
92
93 ['tabs', 'types', 'Tab', 'properties', 'url']
94 '''
95
96 def __init__(self, availability_finder, namespace_name):
97 self._lookup_path = []
98 self._node_availabilities = availability_finder.GetAPINodeAvailability(
99 namespace_name)
100 self._namespace_name = namespace_name
101
102 def _AssertIsValidCategory(self, category):
103 assert category in _NODE_CATEGORIES, \
104 '%s is not a valid category. Full path: %s' % (category,
105 self._lookup_path)
106
107 def _GetParentPath(self):
108 '''Returns the path pointing to this node's parent.
109 '''
110 assert len(self._lookup_path) > 1, \
111 'Tried to look up parent for the top-level node.'
112
113 # lookup_path[-1] is the name of the current node. If this lookup_path
114 # describes a regular node, then lookup_path[-2] will be a node category.
115 # Otherwise, it's an event callback or a function parameter.
116 if self._lookup_path[-2] not in _NODE_CATEGORIES:
117 if self._lookup_path[-1] == 'callback':
118 # This is an event callback, so lookup_path[-2] is the event
119 # node name, thus lookup_path[-3] must be 'events'.
120 assert self._lookup_path[-3] == 'events'
121 return self._lookup_path[:-1]
122 # This is a function parameter.
123 assert self._lookup_path[-2] == 'parameters'
124 return self._lookup_path[:-2]
125 # This is a regular node, so lookup_path[-2] should
126 # be a node category.
127 self._AssertIsValidCategory(self._lookup_path[-2])
128 return self._lookup_path[:-2]
129
130 def _LookupNodeAvailability(self):
131 '''Returns the ChannelInfo object for this node.
132 '''
133 return self._node_availabilities.Lookup(self._namespace_name,
134 *self._lookup_path).annotation
135
136 def _LookupParentNodeAvailability(self):
137 '''Returns the ChannelInfo object for this node's parent.
138 '''
139 return self._node_availabilities.Lookup(self._namespace_name,
140 *self._GetParentPath()).annotation
141
142 def _CheckNamespacePrefix(self):
143 '''API schemas may prepend the namespace name to top-level types
144 (e.g. declarativeWebRequest > types > declarativeWebRequest.IgnoreRules),
145 but just the base name (here, 'IgnoreRules') will be in the |lookup_path|.
146 Try creating an alternate |lookup_path| by adding the namespace name.
147 '''
148 # lookup_path[0] is always the node category (e.g. types, functions, etc.).
149 # Thus, lookup_path[1] is always the top-level node name.
150 self._AssertIsValidCategory(self._lookup_path[0])
151 base_name = self._lookup_path[1]
152 self._lookup_path[1] = '%s.%s' % (self._namespace_name, base_name)
153 try:
154 node_availability = self._LookupNodeAvailability()
155 if node_availability is not None:
156 return node_availability
157 finally:
158 # Restore lookup_path.
159 self._lookup_path[1] = base_name
160 return None
161
162 def _CheckEventCallback(self):
163 '''Within API schemas, an event has a list of 'properties' that the event's
164 callback expects. The callback itself is not explicitly represented in the
165 schema. However, when creating an event node in _JSCModel, a callback node
166 is generated and acts as the parent for the event's properties.
167 Modify |lookup_path| to check the original schema format.
168 '''
169 if 'events' in self._lookup_path:
170 assert 'callback' in self._lookup_path
171 callback_index = self._lookup_path.index('callback')
172 try:
173 self._lookup_path.pop(callback_index)
174 node_availability = self._LookupNodeAvailability()
175 finally:
176 self._lookup_path.insert(callback_index, 'callback')
177 return node_availability
178 return None
179
180 def _LookupAvailability(self):
181 '''Runs all the lookup checks on self._lookup_path and
182 returns the node availability if found, None otherwise.
183 '''
184 for lookup in (self._LookupNodeAvailability,
185 self._CheckEventCallback,
186 self._CheckNamespacePrefix):
187 node_availability = lookup()
188 if node_availability is not None:
189 return node_availability
190 return None
191
192 def GetAvailability(self):
193 '''Returns availability information for this node.
194 '''
195 node_availability = self._LookupAvailability()
196 if node_availability is None:
197 logging.warning('No availability found for: %s > %s' %
198 (self._namespace_name, ' > '.join(self._lookup_path)))
199 return None
200
201 try:
202 current_path = self._lookup_path
203 self._lookup_path = self._GetParentPath()
204 parent_node_availability = self._LookupAvailability()
205 finally:
206 self._lookup_path = current_path
207 # If the parent node availability couldn't be found, something
208 # is very wrong.
209 assert parent_node_availability is not None
210
211 # Only render this node's availability if it differs from the parent
212 # node's availability.
213 if node_availability == parent_node_availability:
214 return None
215 return node_availability
216
217 def Descend(self, *path):
218 '''Moves down the APISchemaGraph, following |path|.
219 '''
220 class scope(object):
221 def __enter__(self2):
222 self._lookup_path.extend(path)
223 def __exit__(self2, _, __, ___):
224 self._lookup_path[:] = self._lookup_path[:-len(path)]
225 return scope()
226
227
68 class _JSCModel(object): 228 class _JSCModel(object):
69 '''Uses a Model from the JSON Schema Compiler and generates a dict that 229 '''Uses a Model from the JSON Schema Compiler and generates a dict that
70 a Handlebar template can use for a data source. 230 a Handlebar template can use for a data source.
71 ''' 231 '''
72 232
73 def __init__(self, 233 def __init__(self,
74 namespace, 234 namespace,
75 availability_finder, 235 availability_finder,
76 json_cache, 236 json_cache,
77 template_cache, 237 template_cache,
78 features_bundle, 238 features_bundle,
79 event_byname_future): 239 event_byname_future):
80 self._availability = availability_finder.GetAPIAvailability(namespace.name) 240 self._availability = availability_finder.GetAPIAvailability(namespace.name)
241 self._current_node = _APINodeCursor(availability_finder, namespace.name)
81 self._api_availabilities = json_cache.GetFromFile( 242 self._api_availabilities = json_cache.GetFromFile(
82 posixpath.join(JSON_TEMPLATES, 'api_availabilities.json')) 243 posixpath.join(JSON_TEMPLATES, 'api_availabilities.json'))
83 self._intro_tables = json_cache.GetFromFile( 244 self._intro_tables = json_cache.GetFromFile(
84 posixpath.join(JSON_TEMPLATES, 'intro_tables.json')) 245 posixpath.join(JSON_TEMPLATES, 'intro_tables.json'))
85 self._api_features = features_bundle.GetAPIFeatures() 246 self._api_features = features_bundle.GetAPIFeatures()
86 self._template_cache = template_cache 247 self._template_cache = template_cache
87 self._event_byname_future = event_byname_future 248 self._event_byname_future = event_byname_future
88 self._namespace = namespace 249 self._namespace = namespace
89 250
90 def _GetLink(self, link): 251 def _GetLink(self, link):
(...skipping 29 matching lines...) Expand all
120 if not self._IsExperimental(): 281 if not self._IsExperimental():
121 return { 282 return {
122 self._availability.channel_info.channel: True 283 self._availability.channel_info.channel: True
123 } 284 }
124 return None 285 return None
125 286
126 def _IsExperimental(self): 287 def _IsExperimental(self):
127 return self._namespace.name.startswith('experimental') 288 return self._namespace.name.startswith('experimental')
128 289
129 def _GenerateTypes(self, types): 290 def _GenerateTypes(self, types):
130 return [self._GenerateType(t) for t in types] 291 with self._current_node.Descend('types'):
292 return [self._GenerateType(t) for t in types]
131 293
132 def _GenerateType(self, type_): 294 def _GenerateType(self, type_):
133 type_dict = { 295 with self._current_node.Descend(type_.simple_name):
134 'name': type_.simple_name, 296 type_dict = {
135 'description': type_.description, 297 'name': type_.simple_name,
136 'properties': self._GenerateProperties(type_.properties), 298 'description': type_.description,
137 'functions': self._GenerateFunctions(type_.functions), 299 'properties': self._GenerateProperties(type_.properties),
138 'events': self._GenerateEvents(type_.events), 300 'functions': self._GenerateFunctions(type_.functions),
139 'id': _CreateId(type_, 'type') 301 'events': self._GenerateEvents(type_.events),
140 } 302 'id': _CreateId(type_, 'type'),
141 self._RenderTypeInformation(type_, type_dict) 303 }
142 return type_dict 304 self._RenderTypeInformation(type_, type_dict)
305 return type_dict
143 306
144 def _GenerateFunctions(self, functions): 307 def _GenerateFunctions(self, functions):
145 return [self._GenerateFunction(f) for f in functions.values()] 308 with self._current_node.Descend('functions'):
309 return [self._GenerateFunction(f) for f in functions.values()]
146 310
147 def _GenerateFunction(self, function): 311 def _GenerateFunction(self, function):
148 function_dict = { 312 with self._current_node.Descend(function.simple_name):
149 'name': function.simple_name, 313 function_dict = {
150 'description': function.description, 314 'name': function.simple_name,
151 'callback': self._GenerateCallback(function.callback), 315 'description': function.description,
152 'parameters': [], 316 'callback': self._GenerateCallback(function.callback),
153 'returns': None, 317 'parameters': [],
154 'id': _CreateId(function, 'method') 318 'returns': None,
155 } 319 'id': _CreateId(function, 'method'),
156 self._AddCommonProperties(function_dict, function) 320 'availability': self._GetAvailabilityTemplate()
157 if function.returns: 321 }
158 function_dict['returns'] = self._GenerateType(function.returns) 322 self._AddCommonProperties(function_dict, function)
159 for param in function.params: 323 if function.returns:
160 function_dict['parameters'].append(self._GenerateProperty(param)) 324 function_dict['returns'] = self._GenerateType(function.returns)
161 if function.callback is not None: 325 for param in function.params:
162 # Show the callback as an extra parameter. 326 function_dict['parameters'].append(self._GenerateProperty(param))
163 function_dict['parameters'].append( 327 if function.callback is not None:
164 self._GenerateCallbackProperty(function.callback)) 328 # Show the callback as an extra parameter.
165 if len(function_dict['parameters']) > 0: 329 function_dict['parameters'].append(
166 function_dict['parameters'][-1]['last'] = True 330 self._GenerateCallbackProperty(function.callback))
167 return function_dict 331 if len(function_dict['parameters']) > 0:
332 function_dict['parameters'][-1]['last'] = True
333 return function_dict
168 334
169 def _GenerateEvents(self, events): 335 def _GenerateEvents(self, events):
170 return [self._GenerateEvent(e) for e in events.values() 336 with self._current_node.Descend('events'):
171 if not e.supports_dom] 337 return [self._GenerateEvent(e) for e in events.values()
338 if not e.supports_dom]
172 339
173 def _GenerateDomEvents(self, events): 340 def _GenerateDomEvents(self, events):
174 return [self._GenerateEvent(e) for e in events.values() 341 with self._current_node.Descend('events'):
175 if e.supports_dom] 342 return [self._GenerateEvent(e) for e in events.values()
343 if e.supports_dom]
176 344
177 def _GenerateEvent(self, event): 345 def _GenerateEvent(self, event):
178 event_dict = { 346 with self._current_node.Descend(event.simple_name):
179 'name': event.simple_name, 347 event_dict = {
180 'description': event.description, 348 'name': event.simple_name,
181 'filters': [self._GenerateProperty(f) for f in event.filters], 349 'description': event.description,
182 'conditions': [self._GetLink(condition) 350 'filters': [self._GenerateProperty(f) for f in event.filters],
183 for condition in event.conditions], 351 'conditions': [self._GetLink(condition)
184 'actions': [self._GetLink(action) for action in event.actions], 352 for condition in event.conditions],
185 'supportsRules': event.supports_rules, 353 'actions': [self._GetLink(action) for action in event.actions],
186 'supportsListeners': event.supports_listeners, 354 'supportsRules': event.supports_rules,
187 'properties': [], 355 'supportsListeners': event.supports_listeners,
188 'id': _CreateId(event, 'event'), 356 'properties': [],
189 'byName': {}, 357 'id': _CreateId(event, 'event'),
190 } 358 'byName': {},
191 self._AddCommonProperties(event_dict, event)
192 # Add the Event members to each event in this object.
193 if self._event_byname_future:
194 event_dict['byName'].update(self._event_byname_future.Get())
195 # We need to create the method description for addListener based on the
196 # information stored in |event|.
197 if event.supports_listeners:
198 callback_object = model.Function(parent=event,
199 name='callback',
200 json={},
201 namespace=event.parent,
202 origin='')
203 callback_object.params = event.params
204 if event.callback:
205 callback_object.callback = event.callback
206 callback_parameters = self._GenerateCallbackProperty(callback_object)
207 callback_parameters['last'] = True
208 event_dict['byName']['addListener'] = {
209 'name': 'addListener',
210 'callback': self._GenerateFunction(callback_object),
211 'parameters': [callback_parameters]
212 } 359 }
213 if event.supports_dom: 360 self._AddCommonProperties(event_dict, event)
214 # Treat params as properties of the custom Event object associated with 361 # Add the Event members to each event in this object.
215 # this DOM Event. 362 if self._event_byname_future:
216 event_dict['properties'] += [self._GenerateProperty(param) 363 event_dict['byName'].update(self._event_byname_future.Get())
217 for param in event.params] 364 # We need to create the method description for addListener based on the
218 return event_dict 365 # information stored in |event|.
366 if event.supports_listeners:
367 callback_object = model.Function(parent=event,
368 name='callback',
369 json={},
370 namespace=event.parent,
371 origin='')
372 callback_object.params = event.params
373 if event.callback:
374 callback_object.callback = event.callback
375 callback_parameters = self._GenerateCallbackProperty(callback_object)
376 callback_parameters['last'] = True
377 event_dict['byName']['addListener'] = {
378 'name': 'addListener',
379 'callback': self._GenerateFunction(callback_object),
380 'parameters': [callback_parameters]
381 }
382 if event.supports_dom:
383 # Treat params as properties of the custom Event object associated with
384 # this DOM Event.
385 event_dict['properties'] += [self._GenerateProperty(param)
386 for param in event.params]
387 return event_dict
219 388
220 def _GenerateCallback(self, callback): 389 def _GenerateCallback(self, callback):
221 if not callback: 390 if not callback:
222 return None 391 return None
223 callback_dict = { 392 callback_dict = {
224 'name': callback.simple_name, 393 'name': callback.simple_name,
225 'simple_type': {'simple_type': 'function'}, 394 'simple_type': {'simple_type': 'function'},
226 'optional': callback.optional, 395 'optional': callback.optional,
227 'parameters': [] 396 'parameters': []
228 } 397 }
(...skipping 21 matching lines...) Expand all
250 properties = type_.properties 419 properties = type_.properties
251 420
252 property_dict = { 421 property_dict = {
253 'name': property_.simple_name, 422 'name': property_.simple_name,
254 'optional': property_.optional, 423 'optional': property_.optional,
255 'description': property_.description, 424 'description': property_.description,
256 'properties': self._GenerateProperties(type_.properties), 425 'properties': self._GenerateProperties(type_.properties),
257 'functions': self._GenerateFunctions(type_.functions), 426 'functions': self._GenerateFunctions(type_.functions),
258 'parameters': [], 427 'parameters': [],
259 'returns': None, 428 'returns': None,
260 'id': _CreateId(property_, 'property') 429 'id': _CreateId(property_, 'property'),
261 } 430 }
262 self._AddCommonProperties(property_dict, property_) 431 self._AddCommonProperties(property_dict, property_)
263 432
264 if type_.property_type == model.PropertyType.FUNCTION: 433 if type_.property_type == model.PropertyType.FUNCTION:
265 function = type_.function 434 function = type_.function
266 for param in function.params: 435 for param in function.params:
267 property_dict['parameters'].append(self._GenerateProperty(param)) 436 property_dict['parameters'].append(self._GenerateProperty(param))
268 if function.returns: 437 if function.returns:
269 property_dict['returns'] = self._GenerateType(function.returns) 438 property_dict['returns'] = self._GenerateType(function.returns)
270 439
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 # if they share the same 'title' attribute. 498 # if they share the same 'title' attribute.
330 row_titles = [row['title'] for row in intro_rows] 499 row_titles = [row['title'] for row in intro_rows]
331 for misc_row in self._GetMiscIntroRows(): 500 for misc_row in self._GetMiscIntroRows():
332 if misc_row['title'] in row_titles: 501 if misc_row['title'] in row_titles:
333 intro_rows[row_titles.index(misc_row['title'])] = misc_row 502 intro_rows[row_titles.index(misc_row['title'])] = misc_row
334 else: 503 else:
335 intro_rows.append(misc_row) 504 intro_rows.append(misc_row)
336 505
337 return intro_rows 506 return intro_rows
338 507
508 def _GetAvailabilityTemplate(self, status=None, version=None, scheduled=None):
509 '''Returns an object that the templates use to display availability
510 information.
511 '''
512 if status is None:
513 availability_info = self._current_node.GetAvailability()
514 if availability_info is None:
515 return None
516 status = availability_info.channel
517 version = availability_info.version
518 return {
519 'partial': self._template_cache.GetFromFile(
520 '%sintro_tables/%s_message.html' % (PRIVATE_TEMPLATES, status)).Get(),
521 'scheduled': scheduled,
522 'version': version
523 }
524
339 def _GetIntroDescriptionRow(self): 525 def _GetIntroDescriptionRow(self):
340 ''' Generates the 'Description' row data for an API intro table. 526 ''' Generates the 'Description' row data for an API intro table.
341 ''' 527 '''
342 return { 528 return {
343 'title': 'Description', 529 'title': 'Description',
344 'content': [ 530 'content': [
345 { 'text': self._namespace.description } 531 { 'text': self._namespace.description }
346 ] 532 ]
347 } 533 }
348 534
349 def _GetIntroAvailabilityRow(self): 535 def _GetIntroAvailabilityRow(self):
350 ''' Generates the 'Availability' row data for an API intro table. 536 ''' Generates the 'Availability' row data for an API intro table.
351 ''' 537 '''
352 if self._IsExperimental(): 538 if self._IsExperimental():
353 status = 'experimental' 539 status = 'experimental'
354 version = None 540 version = None
355 scheduled = None 541 scheduled = None
356 else: 542 else:
357 status = self._availability.channel_info.channel 543 status = self._availability.channel_info.channel
358 version = self._availability.channel_info.version 544 version = self._availability.channel_info.version
359 scheduled = self._availability.scheduled 545 scheduled = self._availability.scheduled
360 return { 546 return {
361 'title': 'Availability', 547 'title': 'Availability',
362 'content': [{ 548 'content': [
363 'partial': self._template_cache.GetFromFile( 549 self._GetAvailabilityTemplate(status=status,
364 posixpath.join(PRIVATE_TEMPLATES, 550 version=version,
365 'intro_tables', 551 scheduled=scheduled)
366 '%s_message.html' % status)).Get(), 552 ]
367 'version': version,
368 'scheduled': scheduled
369 }]
370 } 553 }
371 554
372 def _GetIntroDependencyRows(self): 555 def _GetIntroDependencyRows(self):
373 # Devtools aren't in _api_features. If we're dealing with devtools, bail. 556 # Devtools aren't in _api_features. If we're dealing with devtools, bail.
374 if 'devtools' in self._namespace.name: 557 if 'devtools' in self._namespace.name:
375 return [] 558 return []
376 559
377 api_feature = self._api_features.Get().get(self._namespace.name) 560 api_feature = self._api_features.Get().get(self._namespace.name)
378 if not api_feature: 561 if not api_feature:
379 logging.error('"%s" not found in _api_features.json' % 562 logging.error('"%s" not found in _api_features.json' %
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 getter = lambda: 0 718 getter = lambda: 0
536 getter.get = lambda api_name: self._GetImpl(platform, api_name).Get() 719 getter.get = lambda api_name: self._GetImpl(platform, api_name).Get()
537 return getter 720 return getter
538 721
539 def Cron(self): 722 def Cron(self):
540 futures = [] 723 futures = []
541 for platform in GetPlatforms(): 724 for platform in GetPlatforms():
542 futures += [self._GetImpl(platform, name) 725 futures += [self._GetImpl(platform, name)
543 for name in self._platform_bundle.GetAPIModels(platform).GetNames()] 726 for name in self._platform_bundle.GetAPIModels(platform).GetNames()]
544 return Collect(futures, except_pass=FileNotFoundError) 727 return Collect(futures, except_pass=FileNotFoundError)
OLDNEW
« no previous file with comments | « no previous file | chrome/common/extensions/docs/server2/api_data_source_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698