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 |