Chromium Code Reviews| 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 environment import IsPreviewServer | 11 from environment import IsPreviewServer |
| 11 from extensions_paths import JSON_TEMPLATES, PRIVATE_TEMPLATES | 12 from extensions_paths import JSON_TEMPLATES, PRIVATE_TEMPLATES |
| 13 from file_system import FileNotFoundError | |
| 14 from future import Future, Collect | |
| 12 import third_party.json_schema_compiler.json_parse as json_parse | 15 import third_party.json_schema_compiler.json_parse as json_parse |
| 13 import third_party.json_schema_compiler.model as model | 16 import third_party.json_schema_compiler.model as model |
| 14 from environment import IsPreviewServer | 17 from environment import IsPreviewServer |
| 15 from third_party.json_schema_compiler.memoize import memoize | 18 from third_party.json_schema_compiler.memoize import memoize |
| 16 | 19 |
| 17 | 20 |
| 18 def _CreateId(node, prefix): | 21 def _CreateId(node, prefix): |
| 19 if node.parent is not None and not isinstance(node.parent, model.Namespace): | 22 if node.parent is not None and not isinstance(node.parent, model.Namespace): |
| 20 return '-'.join([prefix, node.parent.simple_name, node.simple_name]) | 23 return '-'.join([prefix, node.parent.simple_name, node.simple_name]) |
| 21 return '-'.join([prefix, node.simple_name]) | 24 return '-'.join([prefix, node.simple_name]) |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 | 64 |
| 62 | 65 |
| 63 class _JSCModel(object): | 66 class _JSCModel(object): |
| 64 '''Uses a Model from the JSON Schema Compiler and generates a dict that | 67 '''Uses a Model from the JSON Schema Compiler and generates a dict that |
| 65 a Handlebar template can use for a data source. | 68 a Handlebar template can use for a data source. |
| 66 ''' | 69 ''' |
| 67 | 70 |
| 68 def __init__(self, | 71 def __init__(self, |
| 69 api_name, | 72 api_name, |
| 70 api_models, | 73 api_models, |
| 71 disable_refs, | |
| 72 availability_finder, | 74 availability_finder, |
| 73 json_cache, | 75 json_cache, |
| 74 template_cache, | 76 template_cache, |
| 75 features_bundle, | 77 features_bundle, |
| 76 event_byname_function): | 78 event_byname_function): |
| 77 self._disable_refs = disable_refs | |
| 78 self._availability_finder = availability_finder | 79 self._availability_finder = availability_finder |
| 79 self._api_availabilities = json_cache.GetFromFile( | 80 self._api_availabilities = json_cache.GetFromFile( |
| 80 posixpath.join(JSON_TEMPLATES, 'api_availabilities.json')) | 81 posixpath.join(JSON_TEMPLATES, 'api_availabilities.json')) |
| 81 self._intro_tables = json_cache.GetFromFile( | 82 self._intro_tables = json_cache.GetFromFile( |
| 82 posixpath.join(JSON_TEMPLATES, 'intro_tables.json')) | 83 posixpath.join(JSON_TEMPLATES, 'intro_tables.json')) |
| 83 self._api_features = features_bundle.GetAPIFeatures() | 84 self._api_features = features_bundle.GetAPIFeatures() |
| 84 self._template_cache = template_cache | 85 self._template_cache = template_cache |
| 85 self._event_byname_function = event_byname_function | 86 self._event_byname_function = event_byname_function |
| 86 self._namespace = api_models.GetModel(api_name).Get() | 87 self._namespace = api_models.GetModel(api_name).Get() |
|
not at google - send to devlin
2014/04/09 16:27:54
see comment below about cron. this is one of those
| |
| 87 | 88 |
| 88 def _GetLink(self, link): | 89 def _GetLink(self, link): |
| 89 ref = link if '.' in link else (self._namespace.name + '.' + link) | 90 ref = link if '.' in link else (self._namespace.name + '.' + link) |
| 90 return { 'ref': ref, 'text': link, 'name': link } | 91 return { 'ref': ref, 'text': link, 'name': link } |
| 91 | 92 |
| 92 def ToDict(self): | 93 def ToDict(self): |
| 93 if self._namespace is None: | 94 if self._namespace is None: |
| 94 return {} | 95 return {} |
| 95 chrome_dot_name = 'chrome.%s' % self._namespace.name | 96 chrome_dot_name = 'chrome.%s' % self._namespace.name |
| 96 as_dict = { | 97 as_dict = { |
| 97 'name': self._namespace.name, | 98 'name': self._namespace.name, |
| 98 'namespace': self._namespace.documentation_options.get('namespace', | 99 'namespace': self._namespace.documentation_options.get('namespace', |
| 99 chrome_dot_name), | 100 chrome_dot_name), |
| 100 'title': self._namespace.documentation_options.get('title', | 101 'title': self._namespace.documentation_options.get('title', |
| 101 chrome_dot_name), | 102 chrome_dot_name), |
| 102 'documentationOptions': self._namespace.documentation_options, | 103 'documentationOptions': self._namespace.documentation_options, |
| 103 'types': self._GenerateTypes(self._namespace.types.values()), | 104 'types': self._GenerateTypes(self._namespace.types.values()), |
| 104 'functions': self._GenerateFunctions(self._namespace.functions), | 105 'functions': self._GenerateFunctions(self._namespace.functions), |
| 105 'events': self._GenerateEvents(self._namespace.events), | 106 'events': self._GenerateEvents(self._namespace.events), |
| 106 'domEvents': self._GenerateDomEvents(self._namespace.events), | 107 'domEvents': self._GenerateDomEvents(self._namespace.events), |
| 107 'properties': self._GenerateProperties(self._namespace.properties), | 108 'properties': self._GenerateProperties(self._namespace.properties), |
| 109 'introList': self._GetIntroTableList(), | |
| 110 'channelWarning': self._GetChannelWarning(), | |
| 108 } | 111 } |
| 109 if self._namespace.deprecated: | 112 if self._namespace.deprecated: |
| 110 as_dict['deprecated'] = self._namespace.deprecated | 113 as_dict['deprecated'] = self._namespace.deprecated |
| 111 # Rendering the intro list is really expensive and there's no point doing it | 114 |
| 112 # unless we're rending the page - and disable_refs=True implies we're not. | |
| 113 if not self._disable_refs: | |
| 114 as_dict.update({ | |
| 115 'introList': self._GetIntroTableList(), | |
| 116 'channelWarning': self._GetChannelWarning(), | |
| 117 }) | |
| 118 as_dict['byName'] = _GetByNameDict(as_dict) | 115 as_dict['byName'] = _GetByNameDict(as_dict) |
| 119 return as_dict | 116 return as_dict |
| 120 | 117 |
| 121 def _GetApiAvailability(self): | 118 def _GetApiAvailability(self): |
| 122 return self._availability_finder.GetApiAvailability(self._namespace.name) | 119 return self._availability_finder.GetApiAvailability(self._namespace.name) |
| 123 | 120 |
| 124 def _GetChannelWarning(self): | 121 def _GetChannelWarning(self): |
| 125 if not self._IsExperimental(): | 122 if not self._IsExperimental(): |
| 126 return { self._GetApiAvailability().channel: True } | 123 return { self._GetApiAvailability().channel: True } |
| 127 return None | 124 return None |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 for condition in event.conditions], | 183 for condition in event.conditions], |
| 187 'actions': [self._GetLink(action) for action in event.actions], | 184 'actions': [self._GetLink(action) for action in event.actions], |
| 188 'supportsRules': event.supports_rules, | 185 'supportsRules': event.supports_rules, |
| 189 'supportsListeners': event.supports_listeners, | 186 'supportsListeners': event.supports_listeners, |
| 190 'properties': [], | 187 'properties': [], |
| 191 'id': _CreateId(event, 'event'), | 188 'id': _CreateId(event, 'event'), |
| 192 'byName': {}, | 189 'byName': {}, |
| 193 } | 190 } |
| 194 self._AddCommonProperties(event_dict, event) | 191 self._AddCommonProperties(event_dict, event) |
| 195 # Add the Event members to each event in this object. | 192 # Add the Event members to each event in this object. |
| 196 # If refs are disabled then don't worry about this, since it's only needed | 193 if self._event_byname_function: |
| 197 # for rendering, and disable_refs=True implies we're not rendering. | |
| 198 if self._event_byname_function and not self._disable_refs: | |
| 199 event_dict['byName'].update(self._event_byname_function()) | 194 event_dict['byName'].update(self._event_byname_function()) |
| 200 # We need to create the method description for addListener based on the | 195 # We need to create the method description for addListener based on the |
| 201 # information stored in |event|. | 196 # information stored in |event|. |
| 202 if event.supports_listeners: | 197 if event.supports_listeners: |
| 203 callback_object = model.Function(parent=event, | 198 callback_object = model.Function(parent=event, |
| 204 name='callback', | 199 name='callback', |
| 205 json={}, | 200 json={}, |
| 206 namespace=event.parent, | 201 namespace=event.parent, |
| 207 origin='') | 202 origin='') |
| 208 callback_object.params = event.params | 203 callback_object.params = event.params |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 ''' | 456 ''' |
| 462 | 457 |
| 463 def __init__(self, api_name, samples): | 458 def __init__(self, api_name, samples): |
| 464 self._api_name = api_name | 459 self._api_name = api_name |
| 465 self._samples = samples | 460 self._samples = samples |
| 466 | 461 |
| 467 def get(self, key): | 462 def get(self, key): |
| 468 return self._samples.FilterSamples(key, self._api_name) | 463 return self._samples.FilterSamples(key, self._api_name) |
| 469 | 464 |
| 470 | 465 |
| 471 class APIDataSource(object): | 466 class APIDataSource(DataSource): |
| 472 '''This class fetches and loads JSON APIs from the FileSystem passed in with | 467 '''This class fetches and loads JSON APIs from the FileSystem passed in with |
| 473 |compiled_fs_factory|, so the APIs can be plugged into templates. | 468 |compiled_fs_factory|, so the APIs can be plugged into templates. |
| 474 ''' | 469 ''' |
| 470 def __init__(self, server_instance, request): | |
| 471 self._file_system = server_instance.host_file_system_provider.GetTrunk() | |
|
not at google - send to devlin
2014/04/09 16:27:54
this doesn't need to go on |self| because it's onl
| |
| 472 self._json_cache = server_instance.compiled_fs_factory.ForJson( | |
| 473 self._file_system) | |
| 474 self._template_cache = server_instance.compiled_fs_factory.ForTemplates( | |
| 475 self._file_system) | |
| 476 self._availability_finder = server_instance.availability_finder | |
| 477 self._api_models = server_instance.api_models | |
| 478 self._features_bundle = server_instance.features_bundle | |
| 479 self._model_cache = server_instance.object_store_creator.Create( | |
| 480 APIDataSource) | |
| 475 | 481 |
| 476 class Factory(object): | 482 # This caches the result of _LoadEventByName. |
| 477 def __init__(self, | 483 self._event_byname = None |
| 478 compiled_fs_factory, | 484 self._samples = server_instance.samples_data_source_factory.Create(request) |
| 479 file_system, | |
| 480 availability_finder, | |
| 481 api_models, | |
| 482 features_bundle, | |
| 483 object_store_creator): | |
| 484 self._json_cache = compiled_fs_factory.ForJson(file_system) | |
| 485 self._template_cache = compiled_fs_factory.ForTemplates(file_system) | |
| 486 self._availability_finder = availability_finder | |
| 487 self._api_models = api_models | |
| 488 self._features_bundle = features_bundle | |
| 489 self._model_cache_refs = object_store_creator.Create( | |
| 490 APIDataSource, 'model-cache-refs') | |
| 491 self._model_cache_no_refs = object_store_creator.Create( | |
| 492 APIDataSource, 'model-cache-no-refs') | |
| 493 | 485 |
| 494 # These must be set later via the SetFooDataSourceFactory methods. | 486 def _LoadEventByName(self): |
| 495 self._samples_data_source_factory = None | 487 '''All events have some members in common. We source their description |
| 488 from Event in events.json. | |
| 489 ''' | |
| 490 if self._event_byname is None: | |
| 491 self._event_byname = _GetEventByNameFromEvents( | |
| 492 self._GetSchemaModel('events')) | |
| 493 return self._event_byname | |
| 496 | 494 |
| 497 # This caches the result of _LoadEventByName. | 495 def _GetSchemaModel(self, api_name): |
| 498 self._event_byname = None | 496 jsc_model = self._model_cache.Get(api_name).Get() |
| 499 | 497 if jsc_model is not None: |
| 500 def SetSamplesDataSourceFactory(self, samples_data_source_factory): | |
| 501 self._samples_data_source_factory = samples_data_source_factory | |
| 502 | |
| 503 def Create(self, request): | |
| 504 '''Creates an APIDataSource. | |
| 505 ''' | |
| 506 if self._samples_data_source_factory is None: | |
| 507 # Only error if there is a request, which means this APIDataSource is | |
| 508 # actually being used to render a page. | |
| 509 if request is not None: | |
| 510 logging.error('SamplesDataSource.Factory was never set in ' | |
| 511 'APIDataSource.Factory.') | |
| 512 samples = None | |
| 513 else: | |
| 514 samples = self._samples_data_source_factory.Create(request) | |
| 515 return APIDataSource(self._GetSchemaModel, samples) | |
| 516 | |
| 517 def _LoadEventByName(self): | |
| 518 '''All events have some members in common. We source their description | |
| 519 from Event in events.json. | |
| 520 ''' | |
| 521 if self._event_byname is None: | |
| 522 self._event_byname = _GetEventByNameFromEvents( | |
| 523 self._GetSchemaModel('events', True)) | |
| 524 return self._event_byname | |
| 525 | |
| 526 def _GetModelCache(self, disable_refs): | |
| 527 if disable_refs: | |
| 528 return self._model_cache_no_refs | |
| 529 return self._model_cache_refs | |
| 530 | |
| 531 def _GetSchemaModel(self, api_name, disable_refs): | |
| 532 jsc_model = self._GetModelCache(disable_refs).Get(api_name).Get() | |
| 533 if jsc_model is not None: | |
| 534 return jsc_model | |
| 535 | |
| 536 jsc_model = _JSCModel( | |
| 537 api_name, | |
| 538 self._api_models, | |
| 539 disable_refs, | |
| 540 self._availability_finder, | |
| 541 self._json_cache, | |
| 542 self._template_cache, | |
| 543 self._features_bundle, | |
| 544 self._LoadEventByName).ToDict() | |
| 545 | |
| 546 self._GetModelCache(disable_refs).Set(api_name, jsc_model) | |
| 547 return jsc_model | 498 return jsc_model |
| 548 | 499 |
| 549 def __init__(self, get_schema_model, samples): | 500 jsc_model = _JSCModel( |
| 550 self._get_schema_model = get_schema_model | 501 api_name, |
| 551 self._samples = samples | 502 self._api_models, |
| 503 self._availability_finder, | |
| 504 self._json_cache, | |
| 505 self._template_cache, | |
| 506 self._features_bundle, | |
| 507 self._LoadEventByName).ToDict() | |
| 508 | |
| 509 self._model_cache.Set(api_name, jsc_model) | |
| 510 return jsc_model | |
| 511 | |
| 552 | 512 |
| 553 def _GenerateHandlebarContext(self, handlebar_dict): | 513 def _GenerateHandlebarContext(self, handlebar_dict): |
| 554 # Parsing samples on the preview server takes seconds and doesn't add | 514 # Parsing samples on the preview server takes seconds and doesn't add |
| 555 # anything. Don't do it. | 515 # anything. Don't do it. |
| 556 if not IsPreviewServer(): | 516 if not IsPreviewServer(): |
| 557 handlebar_dict['samples'] = _LazySamplesGetter( | 517 handlebar_dict['samples'] = _LazySamplesGetter( |
| 558 handlebar_dict['name'], | 518 handlebar_dict['name'], |
| 559 self._samples) | 519 self._samples) |
| 560 return handlebar_dict | 520 return handlebar_dict |
| 561 | 521 |
| 562 def get(self, api_name, disable_refs=False): | 522 def get(self, api_name): |
|
ahernandez
2014/04/08 17:45:06
The only class using |disable_refs| was ReferenceR
not at google - send to devlin
2014/04/09 16:27:54
Awesome.
| |
| 563 return self._GenerateHandlebarContext( | 523 return self._GenerateHandlebarContext(self._GetSchemaModel(api_name)) |
| 564 self._get_schema_model(api_name, disable_refs)) | 524 |
| 525 def Cron(self): | |
| 526 futures = [] | |
| 527 try: | |
| 528 futures.extend([Future(value=self.get(api_name)) | |
|
not at google - send to devlin
2014/04/09 16:27:54
setting a value= for each of these defeats the pur
| |
| 529 for api_name in self._api_models.GetNames()]) | |
| 530 except FileNotFoundError: | |
| 531 pass | |
| 532 return Collect(futures) | |
| OLD | NEW |