| OLD | NEW |
| 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 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 then the 'url' property would be represented by: | 91 then the 'url' property would be represented by: |
| 92 | 92 |
| 93 ['tabs', 'types', 'Tab', 'properties', 'url'] | 93 ['tabs', 'types', 'Tab', 'properties', 'url'] |
| 94 ''' | 94 ''' |
| 95 | 95 |
| 96 def __init__(self, availability_finder, namespace_name): | 96 def __init__(self, availability_finder, namespace_name): |
| 97 self._lookup_path = [] | 97 self._lookup_path = [] |
| 98 self._node_availabilities = availability_finder.GetAPINodeAvailability( | 98 self._node_availabilities = availability_finder.GetAPINodeAvailability( |
| 99 namespace_name) | 99 namespace_name) |
| 100 self._namespace_name = namespace_name | 100 self._namespace_name = namespace_name |
| 101 self._ignored_categories = [] |
| 101 | 102 |
| 102 def _AssertIsValidCategory(self, category): | 103 def _AssertIsValidCategory(self, category): |
| 103 assert category in _NODE_CATEGORIES, \ | 104 assert category in _NODE_CATEGORIES, \ |
| 104 '%s is not a valid category. Full path: %s' % (category, | 105 '%s is not a valid category. Full path: %s' % (category, str(self)) |
| 105 self._lookup_path) | |
| 106 | 106 |
| 107 def _GetParentPath(self): | 107 def _GetParentPath(self): |
| 108 '''Returns the path pointing to this node's parent. | 108 '''Returns the path pointing to this node's parent. |
| 109 ''' | 109 ''' |
| 110 assert len(self._lookup_path) > 1, \ | 110 assert len(self._lookup_path) > 1, \ |
| 111 'Tried to look up parent for the top-level node.' | 111 'Tried to look up parent for the top-level node.' |
| 112 | 112 |
| 113 # lookup_path[-1] is the name of the current node. If this lookup_path | 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. | 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. | 115 # Otherwise, it's an event callback or a function parameter. |
| 116 if self._lookup_path[-2] not in _NODE_CATEGORIES: | 116 if self._lookup_path[-2] not in _NODE_CATEGORIES: |
| 117 if self._lookup_path[-1] == 'callback': | 117 if self._lookup_path[-1] == 'callback': |
| 118 # This is an event callback, so lookup_path[-2] is the event | 118 # This is an event callback, so lookup_path[-2] is the event |
| 119 # node name, thus lookup_path[-3] must be 'events'. | 119 # node name, thus lookup_path[-3] must be 'events'. |
| 120 assert self._lookup_path[-3] == 'events' | 120 assert self._lookup_path[-3] == 'events' |
| 121 return self._lookup_path[:-1] | 121 return self._lookup_path[:-1] |
| 122 # This is a function parameter. | 122 # This is a function parameter. |
| 123 assert self._lookup_path[-2] == 'parameters' | 123 assert self._lookup_path[-2] == 'parameters' |
| 124 return self._lookup_path[:-2] | 124 return self._lookup_path[:-2] |
| 125 # This is a regular node, so lookup_path[-2] should | 125 # This is a regular node, so lookup_path[-2] should |
| 126 # be a node category. | 126 # be a node category. |
| 127 self._AssertIsValidCategory(self._lookup_path[-2]) | 127 self._AssertIsValidCategory(self._lookup_path[-2]) |
| 128 return self._lookup_path[:-2] | 128 return self._lookup_path[:-2] |
| 129 | 129 |
| 130 def _LookupNodeAvailability(self): | 130 def _LookupNodeAvailability(self, lookup_path): |
| 131 '''Returns the ChannelInfo object for this node. | 131 '''Returns the ChannelInfo object for this node. |
| 132 ''' | 132 ''' |
| 133 return self._node_availabilities.Lookup(self._namespace_name, | 133 return self._node_availabilities.Lookup(self._namespace_name, |
| 134 *self._lookup_path).annotation | 134 *lookup_path).annotation |
| 135 | 135 |
| 136 def _LookupParentNodeAvailability(self): | 136 def _CheckNamespacePrefix(self, lookup_path): |
| 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 | 137 '''API schemas may prepend the namespace name to top-level types |
| 144 (e.g. declarativeWebRequest > types > declarativeWebRequest.IgnoreRules), | 138 (e.g. declarativeWebRequest > types > declarativeWebRequest.IgnoreRules), |
| 145 but just the base name (here, 'IgnoreRules') will be in the |lookup_path|. | 139 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. | 140 Try creating an alternate |lookup_path| by adding the namespace name. |
| 147 ''' | 141 ''' |
| 148 # lookup_path[0] is always the node category (e.g. types, functions, etc.). | 142 # 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. | 143 # Thus, lookup_path[1] is always the top-level node name. |
| 150 self._AssertIsValidCategory(self._lookup_path[0]) | 144 self._AssertIsValidCategory(lookup_path[0]) |
| 151 base_name = self._lookup_path[1] | 145 base_name = lookup_path[1] |
| 152 self._lookup_path[1] = '%s.%s' % (self._namespace_name, base_name) | 146 lookup_path[1] = '%s.%s' % (self._namespace_name, base_name) |
| 153 try: | 147 try: |
| 154 node_availability = self._LookupNodeAvailability() | 148 node_availability = self._LookupNodeAvailability(lookup_path) |
| 155 if node_availability is not None: | 149 if node_availability is not None: |
| 156 return node_availability | 150 return node_availability |
| 157 finally: | 151 finally: |
| 158 # Restore lookup_path. | 152 # Restore lookup_path. |
| 159 self._lookup_path[1] = base_name | 153 lookup_path[1] = base_name |
| 160 return None | 154 return None |
| 161 | 155 |
| 162 def _CheckEventCallback(self): | 156 def _CheckEventCallback(self, lookup_path): |
| 163 '''Within API schemas, an event has a list of 'properties' that the event's | 157 '''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 | 158 callback expects. The callback itself is not explicitly represented in the |
| 165 schema. However, when creating an event node in _JSCModel, a callback node | 159 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. | 160 is generated and acts as the parent for the event's properties. |
| 167 Modify |lookup_path| to check the original schema format. | 161 Modify |lookup_path| to check the original schema format. |
| 168 ''' | 162 ''' |
| 169 if 'events' in self._lookup_path: | 163 if 'events' in lookup_path: |
| 170 assert 'callback' in self._lookup_path | 164 assert 'callback' in lookup_path, self |
| 171 callback_index = self._lookup_path.index('callback') | 165 callback_index = lookup_path.index('callback') |
| 172 try: | 166 try: |
| 173 self._lookup_path.pop(callback_index) | 167 lookup_path.pop(callback_index) |
| 174 node_availability = self._LookupNodeAvailability() | 168 node_availability = self._LookupNodeAvailability(lookup_path) |
| 175 finally: | 169 finally: |
| 176 self._lookup_path.insert(callback_index, 'callback') | 170 lookup_path.insert(callback_index, 'callback') |
| 177 return node_availability | 171 return node_availability |
| 178 return None | 172 return None |
| 179 | 173 |
| 180 def _LookupAvailability(self): | 174 def _LookupAvailability(self, lookup_path): |
| 181 '''Runs all the lookup checks on self._lookup_path and | 175 '''Runs all the lookup checks on self._lookup_path and |
| 182 returns the node availability if found, None otherwise. | 176 returns the node availability if found, None otherwise. |
| 183 ''' | 177 ''' |
| 184 for lookup in (self._LookupNodeAvailability, | 178 for lookup in (self._LookupNodeAvailability, |
| 185 self._CheckEventCallback, | 179 self._CheckEventCallback, |
| 186 self._CheckNamespacePrefix): | 180 self._CheckNamespacePrefix): |
| 187 node_availability = lookup() | 181 node_availability = lookup(lookup_path) |
| 188 if node_availability is not None: | 182 if node_availability is not None: |
| 189 return node_availability | 183 return node_availability |
| 190 return None | 184 return None |
| 191 | 185 |
| 186 def _GetCategory(self): |
| 187 '''Returns the category this node belongs to. |
| 188 ''' |
| 189 if self._lookup_path[-2] in _NODE_CATEGORIES: |
| 190 return self._lookup_path[-2] |
| 191 # If lookup_path[-2] is not in _NODE_CATEGORIES and |
| 192 # lookup_path[-1] is 'callback', then we know we have |
| 193 # an event callback. |
| 194 if self._lookup_path[-1] == 'callback': |
| 195 return 'events' |
| 196 if self._lookup_path[-2] == 'parameters': |
| 197 # Function parameters are modelled as properties. |
| 198 return 'properties' |
| 199 if (self._lookup_path[-1].endswith('Type') and |
| 200 (self._lookup_path[-1][:-len('Type')] == self._lookup_path[-2] or |
| 201 self._lookup_path[-1][:-len('ReturnType')] == self._lookup_path[-2])): |
| 202 # Array elements and function return objects have 'Type' and 'ReturnType' |
| 203 # appended to their names, respectively, in model.py. This results in |
| 204 # lookup paths like |
| 205 # 'events > types > Rule > properties > tags > tagsType'. |
| 206 # These nodes are treated as properties. |
| 207 return 'properties' |
| 208 if self._lookup_path[0] == 'events': |
| 209 # HACK(ahernandez.miralles): This catches a few edge cases, |
| 210 # such as 'webviewTag > events > consolemessage > level'. |
| 211 return 'properties' |
| 212 raise AssertionError('Could not classify node %s' % self) |
| 213 |
| 192 def GetAvailability(self): | 214 def GetAvailability(self): |
| 193 '''Returns availability information for this node. | 215 '''Returns availability information for this node. |
| 194 ''' | 216 ''' |
| 195 node_availability = self._LookupAvailability() | 217 if self._GetCategory() in self._ignored_categories: |
| 218 return None |
| 219 node_availability = self._LookupAvailability(self._lookup_path) |
| 196 if node_availability is None: | 220 if node_availability is None: |
| 197 logging.warning('No availability found for: %s > %s' % | 221 logging.warning('No availability found for: %s' % self) |
| 198 (self._namespace_name, ' > '.join(self._lookup_path))) | |
| 199 return None | 222 return None |
| 200 | 223 |
| 201 try: | 224 parent_node_availability = self._LookupAvailability(self._GetParentPath()) |
| 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 | 225 # If the parent node availability couldn't be found, something |
| 208 # is very wrong. | 226 # is very wrong. |
| 209 assert parent_node_availability is not None | 227 assert parent_node_availability is not None |
| 210 | 228 |
| 211 # Only render this node's availability if it differs from the parent | 229 # Only render this node's availability if it differs from the parent |
| 212 # node's availability. | 230 # node's availability. |
| 213 if node_availability == parent_node_availability: | 231 if node_availability == parent_node_availability: |
| 214 return None | 232 return None |
| 215 return node_availability | 233 return node_availability |
| 216 | 234 |
| 217 def Descend(self, *path): | 235 def Descend(self, *path, **kwargs): |
| 218 '''Moves down the APISchemaGraph, following |path|. | 236 '''Moves down the APISchemaGraph, following |path|. |
| 237 |ignore| should be a tuple of category strings (e.g. ('types',)) |
| 238 for which nodes should not have availability data generated. |
| 219 ''' | 239 ''' |
| 240 ignore = kwargs.get('ignore') |
| 220 class scope(object): | 241 class scope(object): |
| 221 def __enter__(self2): | 242 def __enter__(self2): |
| 222 self._lookup_path.extend(path) | 243 if ignore: |
| 244 self._ignored_categories.extend(ignore) |
| 245 if path: |
| 246 self._lookup_path.extend(path) |
| 247 |
| 223 def __exit__(self2, _, __, ___): | 248 def __exit__(self2, _, __, ___): |
| 224 self._lookup_path[:] = self._lookup_path[:-len(path)] | 249 if ignore: |
| 250 self._ignored_categories[:] = self._ignored_categories[:-len(ignore)] |
| 251 if path: |
| 252 self._lookup_path[:] = self._lookup_path[:-len(path)] |
| 225 return scope() | 253 return scope() |
| 226 | 254 |
| 255 def __str__(self): |
| 256 return repr(self) |
| 257 |
| 258 def __repr__(self): |
| 259 return '%s > %s' % (self._namespace_name, ' > '.join(self._lookup_path)) |
| 260 |
| 227 | 261 |
| 228 class _JSCModel(object): | 262 class _JSCModel(object): |
| 229 '''Uses a Model from the JSON Schema Compiler and generates a dict that | 263 '''Uses a Model from the JSON Schema Compiler and generates a dict that |
| 230 a Handlebar template can use for a data source. | 264 a Handlebar template can use for a data source. |
| 231 ''' | 265 ''' |
| 232 | 266 |
| 233 def __init__(self, | 267 def __init__(self, |
| 234 namespace, | 268 namespace, |
| 235 availability_finder, | 269 availability_finder, |
| 236 json_cache, | 270 json_cache, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 | 327 |
| 294 def _GenerateType(self, type_): | 328 def _GenerateType(self, type_): |
| 295 with self._current_node.Descend(type_.simple_name): | 329 with self._current_node.Descend(type_.simple_name): |
| 296 type_dict = { | 330 type_dict = { |
| 297 'name': type_.simple_name, | 331 'name': type_.simple_name, |
| 298 'description': type_.description, | 332 'description': type_.description, |
| 299 'properties': self._GenerateProperties(type_.properties), | 333 'properties': self._GenerateProperties(type_.properties), |
| 300 'functions': self._GenerateFunctions(type_.functions), | 334 'functions': self._GenerateFunctions(type_.functions), |
| 301 'events': self._GenerateEvents(type_.events), | 335 'events': self._GenerateEvents(type_.events), |
| 302 'id': _CreateId(type_, 'type'), | 336 'id': _CreateId(type_, 'type'), |
| 337 'availability': self._GetAvailabilityTemplate() |
| 303 } | 338 } |
| 304 self._RenderTypeInformation(type_, type_dict) | 339 self._RenderTypeInformation(type_, type_dict) |
| 305 return type_dict | 340 return type_dict |
| 306 | 341 |
| 307 def _GenerateFunctions(self, functions): | 342 def _GenerateFunctions(self, functions): |
| 308 with self._current_node.Descend('functions'): | 343 with self._current_node.Descend('functions'): |
| 309 return [self._GenerateFunction(f) for f in functions.values()] | 344 return [self._GenerateFunction(f) for f in functions.values()] |
| 310 | 345 |
| 311 def _GenerateFunction(self, function): | 346 def _GenerateFunction(self, function): |
| 312 with self._current_node.Descend(function.simple_name): | 347 # When ignoring types, properties must be ignored as well. |
| 348 with self._current_node.Descend(function.simple_name, |
| 349 ignore=('types', 'properties')): |
| 313 function_dict = { | 350 function_dict = { |
| 314 'name': function.simple_name, | 351 'name': function.simple_name, |
| 315 'description': function.description, | 352 'description': function.description, |
| 316 'callback': self._GenerateCallback(function.callback), | 353 'callback': self._GenerateCallback(function.callback), |
| 317 'parameters': [], | 354 'parameters': [], |
| 318 'returns': None, | 355 'returns': None, |
| 319 'id': _CreateId(function, 'method'), | 356 'id': _CreateId(function, 'method'), |
| 320 'availability': self._GetAvailabilityTemplate() | 357 'availability': self._GetAvailabilityTemplate() |
| 321 } | 358 } |
| 322 self._AddCommonProperties(function_dict, function) | 359 self._AddCommonProperties(function_dict, function) |
| 323 if function.returns: | 360 if function.returns: |
| 324 function_dict['returns'] = self._GenerateType(function.returns) | 361 function_dict['returns'] = self._GenerateType(function.returns) |
| 325 for param in function.params: | 362 with self._current_node.Descend(function.simple_name): |
| 326 function_dict['parameters'].append(self._GenerateProperty(param)) | 363 with self._current_node.Descend('parameters'): |
| 364 for param in function.params: |
| 365 function_dict['parameters'].append(self._GenerateProperty(param)) |
| 327 if function.callback is not None: | 366 if function.callback is not None: |
| 328 # Show the callback as an extra parameter. | 367 # Show the callback as an extra parameter. |
| 329 function_dict['parameters'].append( | 368 function_dict['parameters'].append( |
| 330 self._GenerateCallbackProperty(function.callback)) | 369 self._GenerateCallbackProperty(function.callback)) |
| 331 if len(function_dict['parameters']) > 0: | 370 if len(function_dict['parameters']) > 0: |
| 332 function_dict['parameters'][-1]['last'] = True | 371 function_dict['parameters'][-1]['last'] = True |
| 333 return function_dict | 372 return function_dict |
| 334 | 373 |
| 335 def _GenerateEvents(self, events): | 374 def _GenerateEvents(self, events): |
| 336 with self._current_node.Descend('events'): | 375 with self._current_node.Descend('events'): |
| 337 return [self._GenerateEvent(e) for e in events.values() | 376 return [self._GenerateEvent(e) for e in events.values() |
| 338 if not e.supports_dom] | 377 if not e.supports_dom] |
| 339 | 378 |
| 340 def _GenerateDomEvents(self, events): | 379 def _GenerateDomEvents(self, events): |
| 341 with self._current_node.Descend('events'): | 380 with self._current_node.Descend('events'): |
| 342 return [self._GenerateEvent(e) for e in events.values() | 381 return [self._GenerateEvent(e) for e in events.values() |
| 343 if e.supports_dom] | 382 if e.supports_dom] |
| 344 | 383 |
| 345 def _GenerateEvent(self, event): | 384 def _GenerateEvent(self, event): |
| 346 with self._current_node.Descend(event.simple_name): | 385 with self._current_node.Descend(event.simple_name, ignore=('properties',)): |
| 347 event_dict = { | 386 event_dict = { |
| 348 'name': event.simple_name, | 387 'name': event.simple_name, |
| 349 'description': event.description, | 388 'description': event.description, |
| 350 'filters': [self._GenerateProperty(f) for f in event.filters], | 389 'filters': [self._GenerateProperty(f) for f in event.filters], |
| 351 'conditions': [self._GetLink(condition) | 390 'conditions': [self._GetLink(condition) |
| 352 for condition in event.conditions], | 391 for condition in event.conditions], |
| 353 'actions': [self._GetLink(action) for action in event.actions], | 392 'actions': [self._GetLink(action) for action in event.actions], |
| 354 'supportsRules': event.supports_rules, | 393 'supportsRules': event.supports_rules, |
| 355 'supportsListeners': event.supports_listeners, | 394 'supportsListeners': event.supports_listeners, |
| 356 'properties': [], | 395 'properties': [], |
| 357 'id': _CreateId(event, 'event'), | 396 'id': _CreateId(event, 'event'), |
| 358 'byName': {}, | 397 'byName': {}, |
| 398 'availability': self._GetAvailabilityTemplate() |
| 359 } | 399 } |
| 400 with self._current_node.Descend(event.simple_name): |
| 360 self._AddCommonProperties(event_dict, event) | 401 self._AddCommonProperties(event_dict, event) |
| 361 # Add the Event members to each event in this object. | 402 # Add the Event members to each event in this object. |
| 362 if self._event_byname_future: | 403 if self._event_byname_future: |
| 363 event_dict['byName'].update(self._event_byname_future.Get()) | 404 event_dict['byName'].update(self._event_byname_future.Get()) |
| 364 # We need to create the method description for addListener based on the | 405 # We need to create the method description for addListener based on the |
| 365 # information stored in |event|. | 406 # information stored in |event|. |
| 366 if event.supports_listeners: | 407 if event.supports_listeners: |
| 367 callback_object = model.Function(parent=event, | 408 callback_object = model.Function(parent=event, |
| 368 name='callback', | 409 name='callback', |
| 369 json={}, | 410 json={}, |
| 370 namespace=event.parent, | 411 namespace=event.parent, |
| 371 origin='') | 412 origin='') |
| 372 callback_object.params = event.params | 413 callback_object.params = event.params |
| 373 if event.callback: | 414 if event.callback: |
| 374 callback_object.callback = event.callback | 415 callback_object.callback = event.callback |
| 375 callback_parameters = self._GenerateCallbackProperty(callback_object) | 416 callback_parameters = self._GenerateCallbackProperty(callback_object) |
| 376 callback_parameters['last'] = True | 417 callback_parameters['last'] = True |
| 377 event_dict['byName']['addListener'] = { | 418 event_dict['byName']['addListener'] = { |
| 378 'name': 'addListener', | 419 'name': 'addListener', |
| 379 'callback': self._GenerateFunction(callback_object), | 420 'callback': self._GenerateFunction(callback_object), |
| 380 'parameters': [callback_parameters] | 421 'parameters': [callback_parameters] |
| 381 } | 422 } |
| 423 with self._current_node.Descend(event.simple_name, ignore=('properties',)): |
| 382 if event.supports_dom: | 424 if event.supports_dom: |
| 383 # Treat params as properties of the custom Event object associated with | 425 # Treat params as properties of the custom Event object associated with |
| 384 # this DOM Event. | 426 # this DOM Event. |
| 385 event_dict['properties'] += [self._GenerateProperty(param) | 427 event_dict['properties'] += [self._GenerateProperty(param) |
| 386 for param in event.params] | 428 for param in event.params] |
| 387 return event_dict | 429 return event_dict |
| 388 | 430 |
| 389 def _GenerateCallback(self, callback): | 431 def _GenerateCallback(self, callback): |
| 390 if not callback: | 432 if not callback: |
| 391 return None | 433 return None |
| 392 callback_dict = { | 434 callback_dict = { |
| 393 'name': callback.simple_name, | 435 'name': callback.simple_name, |
| 394 'simple_type': {'simple_type': 'function'}, | 436 'simple_type': {'simple_type': 'function'}, |
| 395 'optional': callback.optional, | 437 'optional': callback.optional, |
| 396 'parameters': [] | 438 'parameters': [] |
| 397 } | 439 } |
| 398 for param in callback.params: | 440 with self._current_node.Descend('parameters', |
| 399 callback_dict['parameters'].append(self._GenerateProperty(param)) | 441 callback.simple_name, |
| 442 'parameters'): |
| 443 for param in callback.params: |
| 444 callback_dict['parameters'].append(self._GenerateProperty(param)) |
| 400 if (len(callback_dict['parameters']) > 0): | 445 if (len(callback_dict['parameters']) > 0): |
| 401 callback_dict['parameters'][-1]['last'] = True | 446 callback_dict['parameters'][-1]['last'] = True |
| 402 return callback_dict | 447 return callback_dict |
| 403 | 448 |
| 404 def _GenerateProperties(self, properties): | 449 def _GenerateProperties(self, properties): |
| 405 return [self._GenerateProperty(v) for v in properties.values()] | 450 with self._current_node.Descend('properties'): |
| 451 return [self._GenerateProperty(v) for v in properties.values()] |
| 406 | 452 |
| 407 def _GenerateProperty(self, property_): | 453 def _GenerateProperty(self, property_): |
| 408 if not hasattr(property_, 'type_'): | 454 with self._current_node.Descend(property_.simple_name): |
| 409 for d in dir(property_): | 455 if not hasattr(property_, 'type_'): |
| 410 if not d.startswith('_'): | 456 for d in dir(property_): |
| 411 print ('%s -> %s' % (d, getattr(property_, d))) | 457 if not d.startswith('_'): |
| 412 type_ = property_.type_ | 458 print ('%s -> %s' % (d, getattr(property_, d))) |
| 459 type_ = property_.type_ |
| 413 | 460 |
| 414 # Make sure we generate property info for arrays, too. | 461 # Make sure we generate property info for arrays, too. |
| 415 # TODO(kalman): what about choices? | 462 # TODO(kalman): what about choices? |
| 416 if type_.property_type == model.PropertyType.ARRAY: | 463 if type_.property_type == model.PropertyType.ARRAY: |
| 417 properties = type_.item_type.properties | 464 properties = type_.item_type.properties |
| 418 else: | 465 else: |
| 419 properties = type_.properties | 466 properties = type_.properties |
| 420 | 467 |
| 421 property_dict = { | 468 property_dict = { |
| 422 'name': property_.simple_name, | 469 'name': property_.simple_name, |
| 423 'optional': property_.optional, | 470 'optional': property_.optional, |
| 424 'description': property_.description, | 471 'description': property_.description, |
| 425 'properties': self._GenerateProperties(type_.properties), | 472 'properties': self._GenerateProperties(type_.properties), |
| 426 'functions': self._GenerateFunctions(type_.functions), | 473 'functions': self._GenerateFunctions(type_.functions), |
| 427 'parameters': [], | 474 'parameters': [], |
| 428 'returns': None, | 475 'returns': None, |
| 429 'id': _CreateId(property_, 'property'), | 476 'id': _CreateId(property_, 'property'), |
| 430 } | 477 'availability': self._GetAvailabilityTemplate() |
| 431 self._AddCommonProperties(property_dict, property_) | 478 } |
| 479 self._AddCommonProperties(property_dict, property_) |
| 432 | 480 |
| 433 if type_.property_type == model.PropertyType.FUNCTION: | 481 if type_.property_type == model.PropertyType.FUNCTION: |
| 434 function = type_.function | 482 function = type_.function |
| 435 for param in function.params: | 483 with self._current_node.Descend('parameters'): |
| 436 property_dict['parameters'].append(self._GenerateProperty(param)) | 484 for param in function.params: |
| 437 if function.returns: | 485 property_dict['parameters'].append(self._GenerateProperty(param)) |
| 438 property_dict['returns'] = self._GenerateType(function.returns) | 486 if function.returns: |
| 487 with self._current_node.Descend(ignore=('types', 'properties')): |
| 488 property_dict['returns'] = self._GenerateType(function.returns) |
| 439 | 489 |
| 440 value = property_.value | 490 value = property_.value |
| 441 if value is not None: | 491 if value is not None: |
| 442 if isinstance(value, int): | 492 if isinstance(value, int): |
| 443 property_dict['value'] = _FormatValue(value) | 493 property_dict['value'] = _FormatValue(value) |
| 494 else: |
| 495 property_dict['value'] = value |
| 444 else: | 496 else: |
| 445 property_dict['value'] = value | 497 self._RenderTypeInformation(type_, property_dict) |
| 446 else: | |
| 447 self._RenderTypeInformation(type_, property_dict) | |
| 448 | 498 |
| 449 return property_dict | 499 return property_dict |
| 450 | 500 |
| 451 def _GenerateCallbackProperty(self, callback): | 501 def _GenerateCallbackProperty(self, callback): |
| 452 property_dict = { | 502 property_dict = { |
| 453 'name': callback.simple_name, | 503 'name': callback.simple_name, |
| 454 'description': callback.description, | 504 'description': callback.description, |
| 455 'optional': callback.optional, | 505 'optional': callback.optional, |
| 456 'is_callback': True, | 506 'is_callback': True, |
| 457 'id': _CreateId(callback, 'property'), | 507 'id': _CreateId(callback, 'property'), |
| 458 'simple_type': 'function', | 508 'simple_type': 'function', |
| 459 } | 509 } |
| 460 if (callback.parent is not None and | 510 if (callback.parent is not None and |
| 461 not isinstance(callback.parent, model.Namespace)): | 511 not isinstance(callback.parent, model.Namespace)): |
| 462 property_dict['parentName'] = callback.parent.simple_name | 512 property_dict['parentName'] = callback.parent.simple_name |
| 463 return property_dict | 513 return property_dict |
| 464 | 514 |
| 465 def _RenderTypeInformation(self, type_, dst_dict): | 515 def _RenderTypeInformation(self, type_, dst_dict): |
| 466 dst_dict['is_object'] = type_.property_type == model.PropertyType.OBJECT | 516 with self._current_node.Descend(ignore=('types', 'properties')): |
| 467 if type_.property_type == model.PropertyType.CHOICES: | 517 dst_dict['is_object'] = type_.property_type == model.PropertyType.OBJECT |
| 468 dst_dict['choices'] = self._GenerateTypes(type_.choices) | 518 if type_.property_type == model.PropertyType.CHOICES: |
| 469 # We keep track of which == last for knowing when to add "or" between | 519 dst_dict['choices'] = self._GenerateTypes(type_.choices) |
| 470 # choices in templates. | 520 # We keep track of which == last for knowing when to add "or" between |
| 471 if len(dst_dict['choices']) > 0: | 521 # choices in templates. |
| 472 dst_dict['choices'][-1]['last'] = True | 522 if len(dst_dict['choices']) > 0: |
| 473 elif type_.property_type == model.PropertyType.REF: | 523 dst_dict['choices'][-1]['last'] = True |
| 474 dst_dict['link'] = self._GetLink(type_.ref_type) | 524 elif type_.property_type == model.PropertyType.REF: |
| 475 elif type_.property_type == model.PropertyType.ARRAY: | 525 dst_dict['link'] = self._GetLink(type_.ref_type) |
| 476 dst_dict['array'] = self._GenerateType(type_.item_type) | 526 elif type_.property_type == model.PropertyType.ARRAY: |
| 477 elif type_.property_type == model.PropertyType.ENUM: | 527 dst_dict['array'] = self._GenerateType(type_.item_type) |
| 478 dst_dict['enum_values'] = [ | 528 elif type_.property_type == model.PropertyType.ENUM: |
| 479 {'name': value.name, 'description': value.description} | 529 dst_dict['enum_values'] = [ |
| 480 for value in type_.enum_values] | 530 {'name': value.name, 'description': value.description} |
| 481 if len(dst_dict['enum_values']) > 0: | 531 for value in type_.enum_values] |
| 482 dst_dict['enum_values'][-1]['last'] = True | 532 if len(dst_dict['enum_values']) > 0: |
| 483 elif type_.instance_of is not None: | 533 dst_dict['enum_values'][-1]['last'] = True |
| 484 dst_dict['simple_type'] = type_.instance_of | 534 elif type_.instance_of is not None: |
| 485 else: | 535 dst_dict['simple_type'] = type_.instance_of |
| 486 dst_dict['simple_type'] = type_.property_type.name | 536 else: |
| 537 dst_dict['simple_type'] = type_.property_type.name |
| 487 | 538 |
| 488 def _GetIntroTableList(self): | 539 def _GetIntroTableList(self): |
| 489 '''Create a generic data structure that can be traversed by the templates | 540 '''Create a generic data structure that can be traversed by the templates |
| 490 to create an API intro table. | 541 to create an API intro table. |
| 491 ''' | 542 ''' |
| 492 intro_rows = [ | 543 intro_rows = [ |
| 493 self._GetIntroDescriptionRow(), | 544 self._GetIntroDescriptionRow(), |
| 494 self._GetIntroAvailabilityRow() | 545 self._GetIntroAvailabilityRow() |
| 495 ] + self._GetIntroDependencyRows() | 546 ] + self._GetIntroDependencyRows() |
| 496 | 547 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 getter = lambda: 0 | 769 getter = lambda: 0 |
| 719 getter.get = lambda api_name: self._GetImpl(platform, api_name).Get() | 770 getter.get = lambda api_name: self._GetImpl(platform, api_name).Get() |
| 720 return getter | 771 return getter |
| 721 | 772 |
| 722 def Cron(self): | 773 def Cron(self): |
| 723 futures = [] | 774 futures = [] |
| 724 for platform in GetPlatforms(): | 775 for platform in GetPlatforms(): |
| 725 futures += [self._GetImpl(platform, name) | 776 futures += [self._GetImpl(platform, name) |
| 726 for name in self._platform_bundle.GetAPIModels(platform).GetNames()] | 777 for name in self._platform_bundle.GetAPIModels(platform).GetNames()] |
| 727 return Collect(futures, except_pass=FileNotFoundError) | 778 return Collect(futures, except_pass=FileNotFoundError) |
| OLD | NEW |