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

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: Simpler CSS 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
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 current_path = self._lookup_path
202 self._lookup_path = self._GetParentPath()
203 parent_node_availability = self._LookupAvailability()
204 self._lookup_path = current_path
not at google - send to devlin 2014/07/02 19:26:41 Again, please do this in a try..finally. Though I
205 # If the parent node availability couldn't be found, something
206 # is very wrong.
207 assert parent_node_availability is not None
208
209 # Only render this node's availability if it differs from the parent
210 # node's availability.
211 if node_availability == parent_node_availability:
212 return None
213 return node_availability
214
215 def Descend(self, *path):
216 '''Moves down the APISchemaGraph, following |path|.
217 '''
218 class scope(object):
219 def __enter__(self2):
220 self._lookup_path.extend(path)
221 def __exit__(self2, _, __, ___):
222 self._lookup_path[:] = self._lookup_path[:-len(path)]
223 return scope()
224
225
68 class _JSCModel(object): 226 class _JSCModel(object):
69 '''Uses a Model from the JSON Schema Compiler and generates a dict that 227 '''Uses a Model from the JSON Schema Compiler and generates a dict that
70 a Handlebar template can use for a data source. 228 a Handlebar template can use for a data source.
71 ''' 229 '''
72 230
73 def __init__(self, 231 def __init__(self,
74 namespace, 232 namespace,
75 availability_finder, 233 availability_finder,
76 json_cache, 234 json_cache,
77 template_cache, 235 template_cache,
78 features_bundle, 236 features_bundle,
79 event_byname_future): 237 event_byname_future):
80 self._availability = availability_finder.GetAPIAvailability(namespace.name) 238 self._availability = availability_finder.GetAPIAvailability(namespace.name)
239 self._current_node = _APINodeCursor(availability_finder, namespace.name)
81 self._api_availabilities = json_cache.GetFromFile( 240 self._api_availabilities = json_cache.GetFromFile(
82 posixpath.join(JSON_TEMPLATES, 'api_availabilities.json')) 241 posixpath.join(JSON_TEMPLATES, 'api_availabilities.json'))
83 self._intro_tables = json_cache.GetFromFile( 242 self._intro_tables = json_cache.GetFromFile(
84 posixpath.join(JSON_TEMPLATES, 'intro_tables.json')) 243 posixpath.join(JSON_TEMPLATES, 'intro_tables.json'))
85 self._api_features = features_bundle.GetAPIFeatures() 244 self._api_features = features_bundle.GetAPIFeatures()
86 self._template_cache = template_cache 245 self._template_cache = template_cache
87 self._event_byname_future = event_byname_future 246 self._event_byname_future = event_byname_future
88 self._namespace = namespace 247 self._namespace = namespace
89 248
90 def _GetLink(self, link): 249 def _GetLink(self, link):
(...skipping 29 matching lines...) Expand all
120 if not self._IsExperimental(): 279 if not self._IsExperimental():
121 return { 280 return {
122 self._availability.channel_info.channel: True 281 self._availability.channel_info.channel: True
123 } 282 }
124 return None 283 return None
125 284
126 def _IsExperimental(self): 285 def _IsExperimental(self):
127 return self._namespace.name.startswith('experimental') 286 return self._namespace.name.startswith('experimental')
128 287
129 def _GenerateTypes(self, types): 288 def _GenerateTypes(self, types):
130 return [self._GenerateType(t) for t in types] 289 with self._current_node.Descend('types'):
290 return [self._GenerateType(t) for t in types]
131 291
132 def _GenerateType(self, type_): 292 def _GenerateType(self, type_):
133 type_dict = { 293 with self._current_node.Descend(type_.simple_name):
134 'name': type_.simple_name, 294 type_dict = {
135 'description': type_.description, 295 'name': type_.simple_name,
136 'properties': self._GenerateProperties(type_.properties), 296 'description': type_.description,
137 'functions': self._GenerateFunctions(type_.functions), 297 'properties': self._GenerateProperties(type_.properties),
138 'events': self._GenerateEvents(type_.events), 298 'functions': self._GenerateFunctions(type_.functions),
139 'id': _CreateId(type_, 'type') 299 'events': self._GenerateEvents(type_.events),
140 } 300 'id': _CreateId(type_, 'type'),
141 self._RenderTypeInformation(type_, type_dict) 301 }
142 return type_dict 302 self._RenderTypeInformation(type_, type_dict)
303 return type_dict
143 304
144 def _GenerateFunctions(self, functions): 305 def _GenerateFunctions(self, functions):
145 return [self._GenerateFunction(f) for f in functions.values()] 306 with self._current_node.Descend('functions'):
307 return [self._GenerateFunction(f) for f in functions.values()]
146 308
147 def _GenerateFunction(self, function): 309 def _GenerateFunction(self, function):
148 function_dict = { 310 with self._current_node.Descend(function.simple_name):
149 'name': function.simple_name, 311 function_dict = {
150 'description': function.description, 312 'name': function.simple_name,
151 'callback': self._GenerateCallback(function.callback), 313 'description': function.description,
152 'parameters': [], 314 'callback': self._GenerateCallback(function.callback),
153 'returns': None, 315 'parameters': [],
154 'id': _CreateId(function, 'method') 316 'returns': None,
155 } 317 'id': _CreateId(function, 'method'),
156 self._AddCommonProperties(function_dict, function) 318 'availability': self._GetAvailabilityTemplate()
157 if function.returns: 319 }
158 function_dict['returns'] = self._GenerateType(function.returns) 320 self._AddCommonProperties(function_dict, function)
159 for param in function.params: 321 if function.returns:
160 function_dict['parameters'].append(self._GenerateProperty(param)) 322 function_dict['returns'] = self._GenerateType(function.returns)
161 if function.callback is not None: 323 for param in function.params:
162 # Show the callback as an extra parameter. 324 function_dict['parameters'].append(self._GenerateProperty(param))
163 function_dict['parameters'].append( 325 if function.callback is not None:
164 self._GenerateCallbackProperty(function.callback)) 326 # Show the callback as an extra parameter.
165 if len(function_dict['parameters']) > 0: 327 function_dict['parameters'].append(
166 function_dict['parameters'][-1]['last'] = True 328 self._GenerateCallbackProperty(function.callback))
167 return function_dict 329 if len(function_dict['parameters']) > 0:
330 function_dict['parameters'][-1]['last'] = True
331 return function_dict
168 332
169 def _GenerateEvents(self, events): 333 def _GenerateEvents(self, events):
170 return [self._GenerateEvent(e) for e in events.values() 334 with self._current_node.Descend('events'):
171 if not e.supports_dom] 335 return [self._GenerateEvent(e) for e in events.values()
336 if not e.supports_dom]
172 337
173 def _GenerateDomEvents(self, events): 338 def _GenerateDomEvents(self, events):
174 return [self._GenerateEvent(e) for e in events.values() 339 with self._current_node.Descend('events'):
175 if e.supports_dom] 340 return [self._GenerateEvent(e) for e in events.values()
341 if e.supports_dom]
176 342
177 def _GenerateEvent(self, event): 343 def _GenerateEvent(self, event):
178 event_dict = { 344 with self._current_node.Descend(event.simple_name):
179 'name': event.simple_name, 345 event_dict = {
180 'description': event.description, 346 'name': event.simple_name,
181 'filters': [self._GenerateProperty(f) for f in event.filters], 347 'description': event.description,
182 'conditions': [self._GetLink(condition) 348 'filters': [self._GenerateProperty(f) for f in event.filters],
183 for condition in event.conditions], 349 'conditions': [self._GetLink(condition)
184 'actions': [self._GetLink(action) for action in event.actions], 350 for condition in event.conditions],
185 'supportsRules': event.supports_rules, 351 'actions': [self._GetLink(action) for action in event.actions],
186 'supportsListeners': event.supports_listeners, 352 'supportsRules': event.supports_rules,
187 'properties': [], 353 'supportsListeners': event.supports_listeners,
188 'id': _CreateId(event, 'event'), 354 'properties': [],
189 'byName': {}, 355 'id': _CreateId(event, 'event'),
190 } 356 '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 } 357 }
213 if event.supports_dom: 358 self._AddCommonProperties(event_dict, event)
214 # Treat params as properties of the custom Event object associated with 359 # Add the Event members to each event in this object.
215 # this DOM Event. 360 if self._event_byname_future:
216 event_dict['properties'] += [self._GenerateProperty(param) 361 event_dict['byName'].update(self._event_byname_future.Get())
217 for param in event.params] 362 # We need to create the method description for addListener based on the
218 return event_dict 363 # information stored in |event|.
364 if event.supports_listeners:
365 callback_object = model.Function(parent=event,
366 name='callback',
367 json={},
368 namespace=event.parent,
369 origin='')
370 callback_object.params = event.params
371 if event.callback:
372 callback_object.callback = event.callback
373 callback_parameters = self._GenerateCallbackProperty(callback_object)
374 callback_parameters['last'] = True
375 event_dict['byName']['addListener'] = {
376 'name': 'addListener',
377 'callback': self._GenerateFunction(callback_object),
378 'parameters': [callback_parameters]
379 }
380 if event.supports_dom:
381 # Treat params as properties of the custom Event object associated with
382 # this DOM Event.
383 event_dict['properties'] += [self._GenerateProperty(param)
384 for param in event.params]
385 return event_dict
219 386
220 def _GenerateCallback(self, callback): 387 def _GenerateCallback(self, callback):
221 if not callback: 388 if not callback:
222 return None 389 return None
223 callback_dict = { 390 callback_dict = {
224 'name': callback.simple_name, 391 'name': callback.simple_name,
225 'simple_type': {'simple_type': 'function'}, 392 'simple_type': {'simple_type': 'function'},
226 'optional': callback.optional, 393 'optional': callback.optional,
227 'parameters': [] 394 'parameters': []
228 } 395 }
(...skipping 21 matching lines...) Expand all
250 properties = type_.properties 417 properties = type_.properties
251 418
252 property_dict = { 419 property_dict = {
253 'name': property_.simple_name, 420 'name': property_.simple_name,
254 'optional': property_.optional, 421 'optional': property_.optional,
255 'description': property_.description, 422 'description': property_.description,
256 'properties': self._GenerateProperties(type_.properties), 423 'properties': self._GenerateProperties(type_.properties),
257 'functions': self._GenerateFunctions(type_.functions), 424 'functions': self._GenerateFunctions(type_.functions),
258 'parameters': [], 425 'parameters': [],
259 'returns': None, 426 'returns': None,
260 'id': _CreateId(property_, 'property') 427 'id': _CreateId(property_, 'property'),
261 } 428 }
262 self._AddCommonProperties(property_dict, property_) 429 self._AddCommonProperties(property_dict, property_)
263 430
264 if type_.property_type == model.PropertyType.FUNCTION: 431 if type_.property_type == model.PropertyType.FUNCTION:
265 function = type_.function 432 function = type_.function
266 for param in function.params: 433 for param in function.params:
267 property_dict['parameters'].append(self._GenerateProperty(param)) 434 property_dict['parameters'].append(self._GenerateProperty(param))
268 if function.returns: 435 if function.returns:
269 property_dict['returns'] = self._GenerateType(function.returns) 436 property_dict['returns'] = self._GenerateType(function.returns)
270 437
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 # if they share the same 'title' attribute. 496 # if they share the same 'title' attribute.
330 row_titles = [row['title'] for row in intro_rows] 497 row_titles = [row['title'] for row in intro_rows]
331 for misc_row in self._GetMiscIntroRows(): 498 for misc_row in self._GetMiscIntroRows():
332 if misc_row['title'] in row_titles: 499 if misc_row['title'] in row_titles:
333 intro_rows[row_titles.index(misc_row['title'])] = misc_row 500 intro_rows[row_titles.index(misc_row['title'])] = misc_row
334 else: 501 else:
335 intro_rows.append(misc_row) 502 intro_rows.append(misc_row)
336 503
337 return intro_rows 504 return intro_rows
338 505
506 def _GetAvailabilityTemplate(self, status=None, version=None, scheduled=None):
507 '''Returns an object that the templates use to display availability
508 information.
509 '''
510 if status is None:
511 availability_info = self._current_node.GetAvailability()
512 if availability_info is None:
513 return None
514 status = availability_info.channel
515 version = availability_info.version
516 return {
517 'partial': self._template_cache.GetFromFile(
518 '%sintro_tables/%s_message.html' % (PRIVATE_TEMPLATES, status)).Get(),
519 'scheduled': scheduled,
520 'version': version
521 }
522
339 def _GetIntroDescriptionRow(self): 523 def _GetIntroDescriptionRow(self):
340 ''' Generates the 'Description' row data for an API intro table. 524 ''' Generates the 'Description' row data for an API intro table.
341 ''' 525 '''
342 return { 526 return {
343 'title': 'Description', 527 'title': 'Description',
344 'content': [ 528 'content': [
345 { 'text': self._namespace.description } 529 { 'text': self._namespace.description }
346 ] 530 ]
347 } 531 }
348 532
349 def _GetIntroAvailabilityRow(self): 533 def _GetIntroAvailabilityRow(self):
350 ''' Generates the 'Availability' row data for an API intro table. 534 ''' Generates the 'Availability' row data for an API intro table.
351 ''' 535 '''
352 if self._IsExperimental(): 536 if self._IsExperimental():
353 status = 'experimental' 537 status = 'experimental'
354 version = None 538 version = None
355 scheduled = None 539 scheduled = None
356 else: 540 else:
357 status = self._availability.channel_info.channel 541 status = self._availability.channel_info.channel
358 version = self._availability.channel_info.version 542 version = self._availability.channel_info.version
359 scheduled = self._availability.scheduled 543 scheduled = self._availability.scheduled
360 return { 544 return {
361 'title': 'Availability', 545 'title': 'Availability',
362 'content': [{ 546 'content': [
363 'partial': self._template_cache.GetFromFile( 547 self._GetAvailabilityTemplate(status=status,
364 posixpath.join(PRIVATE_TEMPLATES, 548 version=version,
365 'intro_tables', 549 scheduled=scheduled)
366 '%s_message.html' % status)).Get(), 550 ]
367 'version': version,
368 'scheduled': scheduled
369 }]
370 } 551 }
371 552
372 def _GetIntroDependencyRows(self): 553 def _GetIntroDependencyRows(self):
373 # Devtools aren't in _api_features. If we're dealing with devtools, bail. 554 # Devtools aren't in _api_features. If we're dealing with devtools, bail.
374 if 'devtools' in self._namespace.name: 555 if 'devtools' in self._namespace.name:
375 return [] 556 return []
376 557
377 api_feature = self._api_features.Get().get(self._namespace.name) 558 api_feature = self._api_features.Get().get(self._namespace.name)
378 if not api_feature: 559 if not api_feature:
379 logging.error('"%s" not found in _api_features.json' % 560 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 716 getter = lambda: 0
536 getter.get = lambda api_name: self._GetImpl(platform, api_name).Get() 717 getter.get = lambda api_name: self._GetImpl(platform, api_name).Get()
537 return getter 718 return getter
538 719
539 def Cron(self): 720 def Cron(self):
540 futures = [] 721 futures = []
541 for platform in GetPlatforms(): 722 for platform in GetPlatforms():
542 futures += [self._GetImpl(platform, name) 723 futures += [self._GetImpl(platform, name)
543 for name in self._platform_bundle.GetAPIModels(platform).GetNames()] 724 for name in self._platform_bundle.GetAPIModels(platform).GetNames()]
544 return Collect(futures, except_pass=FileNotFoundError) 725 return Collect(futures, except_pass=FileNotFoundError)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698