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

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

Issue 228723005: Refactor APIDataSource to work with DataSourceRegistry (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/common/extensions/docs/server2/api_data_source_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 from copy import copy 5 from copy import copy
6 import logging 6 import logging
7 import os 7 import os
8 import posixpath 8 import posixpath
9 9
10 from data_source import DataSource
10 from 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
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
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
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)
OLDNEW
« no previous file with comments | « no previous file | chrome/common/extensions/docs/server2/api_data_source_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698