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

Unified Diff: chrome/common/extensions/docs/server2/api_data_source.py

Issue 18323018: Linking AvailabilityFinder with APIDataSource and intro-table templates. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase with master Created 7 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 side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/docs/server2/api_data_source.py
diff --git a/chrome/common/extensions/docs/server2/api_data_source.py b/chrome/common/extensions/docs/server2/api_data_source.py
index 3fdd37587de23c6e4c8eab94d7958da966880ae4..e098dd988035a4cf80b0a3e73f8cda9b0f9bf0a4 100644
--- a/chrome/common/extensions/docs/server2/api_data_source.py
+++ b/chrome/common/extensions/docs/server2/api_data_source.py
@@ -7,6 +7,9 @@ import logging
import os
from collections import defaultdict, Mapping
+from branch_utility import BranchUtility
+import svn_constants
+from third_party.handlebar import Handlebar
import third_party.json_schema_compiler.json_parse as json_parse
import third_party.json_schema_compiler.model as model
import third_party.json_schema_compiler.idl_schema as idl_schema
@@ -103,9 +106,20 @@ class _JSCModel(object):
"""Uses a Model from the JSON Schema Compiler and generates a dict that
a Handlebar template can use for a data source.
"""
- def __init__(self, json, ref_resolver, disable_refs, idl=False):
+ def __init__(self,
+ json,
+ ref_resolver,
+ disable_refs,
+ availability_finder,
+ intro_cache,
+ template_data_source,
+ idl=False):
self._ref_resolver = ref_resolver
self._disable_refs = disable_refs
+ self._availability_finder = availability_finder
+ self._intro_tables = intro_cache.GetFromFile(
+ '%s/intro_tables.json' % svn_constants.JSON_PATH)
+ self._template_data_source = template_data_source
clean_json = copy.deepcopy(json)
if _RemoveNoDocs(clean_json):
self._namespace = None
@@ -132,13 +146,83 @@ class _JSCModel(object):
return {}
return {
'name': self._namespace.name,
- 'description': self._namespace.description,
'types': self._GenerateTypes(self._namespace.types.values()),
'functions': self._GenerateFunctions(self._namespace.functions),
'events': self._GenerateEvents(self._namespace.events),
- 'properties': self._GenerateProperties(self._namespace.properties)
+ 'properties': self._GenerateProperties(self._namespace.properties),
+ 'intro_list': self._GetIntroTableList(),
+ 'channel_warning': self._GetChannelWarning()
}
+ def _GetIntroTableList(self):
+ """Create a generic data structure that can be traversed by the templates
+ to create an API intro table.
+ """
+ intro_list = [{
+ 'title': 'Description',
+ 'content': [
+ { 'text': self._FormatDescription(self._namespace.description) }
+ ]
+ }]
+
+ if self._IsExperimental():
+ status = 'experimental'
+ version = None
+ else:
+ availability = self._GetApiAvailability()
+ status = availability.channel
+ version = availability.version
+ intro_list.append({
+ 'title': 'Availability',
+ 'content': [
+ {
+ 'partial': self._template_data_source.get(
+ 'intro_tables/%s_message.html' % status),
+ 'version': version
+ }
+ ]
+ })
+
+ # Look up the API name in intro_tables.json, which is structured similarly
+ # to the data structure being created. If the name is found, loop through
+ # the attributes and add them to this structure.
+ table_info = self._intro_tables.get(self._namespace.name)
+ if table_info is None:
+ return intro_list
+
+ # The intro tables have a specific ordering that needs to be followed.
+ ordering = ('Permissions', 'Samples', 'Learn More')
+
+ for category in ordering:
+ if category not in table_info.keys():
+ continue
+ # Transform the 'partial' argument from the partial name to the
+ # template itself.
+ content = table_info[category]
+ for node in content:
+ # If there is a 'partial' argument and it hasn't already been
+ # converted to a Handlebar object, transform it to a template.
+ # TODO(epeterson/kalman): figure out why this check is necessary
+ # since it should be caching.
+ if 'partial' in node and not isinstance(node['partial'], Handlebar):
+ node['partial'] = self._template_data_source.get(node['partial'])
+ intro_list.append({
+ 'title': category,
+ 'content': content
+ })
+ return intro_list
+
+ def _GetApiAvailability(self):
+ return self._availability_finder.GetApiAvailability(self._namespace.name)
+
+ def _GetChannelWarning(self):
+ if not self._IsExperimental():
+ return { self._GetApiAvailability().channel: True }
+ return None
+
+ def _IsExperimental(self):
+ return self._namespace.name.startswith('experimental')
+
def _GenerateTypes(self, types):
return [self._GenerateType(t) for t in types]
@@ -325,13 +409,13 @@ class APIDataSource(object):
|compiled_fs_factory|, so the APIs can be plugged into templates.
"""
class Factory(object):
- def __init__(self, compiled_fs_factory, base_path):
+ def __init__(self,
+ compiled_fs_factory,
+ base_path,
+ availability_finder_factory):
def create_compiled_fs(fn, category):
return compiled_fs_factory.Create(fn, APIDataSource, category=category)
- self._permissions_cache = create_compiled_fs(self._LoadPermissions,
- 'permissions')
-
self._json_cache = create_compiled_fs(
lambda api_name, api: self._LoadJsonAPI(api, False),
'json')
@@ -353,7 +437,10 @@ class APIDataSource(object):
self._names_cache = create_compiled_fs(self._GetAllNames, 'names')
self._base_path = base_path
-
+ self._availability_finder = availability_finder_factory.Create()
+ self._intro_cache = create_compiled_fs(
+ lambda _, json: json_parse.Parse(json),
+ 'intro-cache')
# These must be set later via the SetFooDataSourceFactory methods.
self._ref_resolver_factory = None
self._samples_data_source_factory = None
@@ -364,6 +451,10 @@ class APIDataSource(object):
def SetReferenceResolverFactory(self, ref_resolver_factory):
self._ref_resolver_factory = ref_resolver_factory
+ def SetTemplateDataSource(self, template_data_source_factory):
+ # This TemplateDataSource is only being used for fetching template data.
+ self._template_data_source = template_data_source_factory.Create(None, '')
+
def Create(self, request, disable_refs=False):
"""Create an APIDataSource. |disable_refs| specifies whether $ref's in
APIs being processed by the |ToDict| method of _JSCModel follows $ref's
@@ -381,8 +472,7 @@ class APIDataSource(object):
if not disable_refs and self._ref_resolver_factory is None:
logging.error('ReferenceResolver.Factory was never set in '
'APIDataSource.Factory.')
- return APIDataSource(self._permissions_cache,
- self._json_cache,
+ return APIDataSource(self._json_cache,
self._idl_cache,
self._json_cache_no_refs,
self._idl_cache_no_refs,
@@ -392,14 +482,14 @@ class APIDataSource(object):
samples,
disable_refs)
- def _LoadPermissions(self, file_name, json_str):
- return json_parse.Parse(json_str)
-
def _LoadJsonAPI(self, api, disable_refs):
return _JSCModel(
json_parse.Parse(api)[0],
self._ref_resolver_factory.Create() if not disable_refs else None,
- disable_refs).ToDict()
+ disable_refs,
+ self._availability_finder,
+ self._intro_cache,
+ self._template_data_source).ToDict()
def _LoadIdlAPI(self, api, disable_refs):
idl = idl_parser.IDLParser().ParseData(api)
@@ -407,6 +497,9 @@ class APIDataSource(object):
idl_schema.IDLSchema(idl).process()[0],
self._ref_resolver_factory.Create() if not disable_refs else None,
disable_refs,
+ self._availability_finder,
+ self._intro_cache,
+ self._template_data_source,
idl=True).ToDict()
def _GetIDLNames(self, base_dir, apis):
@@ -420,7 +513,6 @@ class APIDataSource(object):
if os.path.splitext(api)[1][1:] in exts]
def __init__(self,
- permissions_cache,
json_cache,
idl_cache,
json_cache_no_refs,
@@ -431,7 +523,6 @@ class APIDataSource(object):
samples,
disable_refs):
self._base_path = base_path
- self._permissions_cache = permissions_cache
self._json_cache = json_cache
self._idl_cache = idl_cache
self._json_cache_no_refs = json_cache_no_refs
@@ -441,51 +532,17 @@ class APIDataSource(object):
self._samples = samples
self._disable_refs = disable_refs
- def _GetFeatureFile(self, filename):
- perms = self._permissions_cache.GetFromFile('%s/%s' %
- (self._base_path, filename))
- return dict((model.UnixName(k), v) for k, v in perms.iteritems())
-
- def _GetFeatureData(self, path):
- # Remove 'experimental_' from path name to match the keys in
- # _permissions_features.json.
- path = model.UnixName(path.replace('experimental_', ''))
-
- for filename in ['_permission_features.json', '_manifest_features.json']:
- feature_data = self._GetFeatureFile(filename).get(path, None)
- if feature_data is not None:
- break
-
- # There are specific cases in which the feature is actually a list of
- # features where only one needs to match; but currently these are only
- # used to whitelist features for specific extension IDs. Filter those out.
- if isinstance(feature_data, list):
- feature_list = feature_data
- feature_data = None
- for single_feature in feature_list:
- if 'whitelist' in single_feature:
- continue
- if feature_data is not None:
- # Note: if you are seeing the exception below, add more heuristics as
- # required to form a single feature.
- raise ValueError('Multiple potential features match %s. I can\'t '
- 'decide which one to use. Please help!' % path)
- feature_data = single_feature
-
- if feature_data and feature_data['channel'] in ('trunk', 'dev', 'beta'):
- feature_data[feature_data['channel']] = True
- return feature_data
-
def _GenerateHandlebarContext(self, handlebar_dict, path):
- handlebar_dict['permissions'] = self._GetFeatureData(path)
handlebar_dict['samples'] = _LazySamplesGetter(path, self._samples)
return handlebar_dict
def _GetAsSubdirectory(self, name):
if name.startswith('experimental_'):
parts = name[len('experimental_'):].split('_', 1)
- parts[1] = 'experimental_%s' % parts[1]
- return '/'.join(parts)
+ if len(parts) > 1:
+ parts[1] = 'experimental_%s' % parts[1]
+ return '/'.join(parts)
+ return '%s/%s' % (parts[0], name)
return name.replace('_', '/', 1)
def get(self, key):
« no previous file with comments | « chrome/common/extensions/api/sync_file_system.idl ('k') | 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