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

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

Issue 12996003: Dynamically generate a heading for Extension Docs API pages (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Minor changes Created 7 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 side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/docs/server2/availability_data_source.py
diff --git a/chrome/common/extensions/docs/server2/availability_data_source.py b/chrome/common/extensions/docs/server2/availability_data_source.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1848567767da9596ba87cdf0baba1dee1ade707
--- /dev/null
+++ b/chrome/common/extensions/docs/server2/availability_data_source.py
@@ -0,0 +1,249 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import logging
+import os
+
+from appengine_url_fetcher import AppEngineUrlFetcher
+from caching_file_system import CachingFileSystem
+from compiled_file_system import CompiledFileSystem
+from subversion_file_system import SubversionFileSystem
+import svn_constants
+from third_party.json_schema_compiler import json_comment_eater
+from third_party.json_schema_compiler import model
+import url_constants
+
+# These labels are used for interacting with AvailabilityDataSource's object
+# store. The format is <label><string> (e.g. svn21, or permissiontabs26)
+SVN = 'svn'
+PERMISSION = 'permission'
+MANIFEST = 'manifest'
+FILESYS = 'filesys'
not at google - send to devlin 2013/04/30 18:34:19 use these in category= when creating the object st
epeterson 2013/05/13 02:38:10 Done.
+
+class AvailabilityDataSource(object):
+ '''Uses API data sources generated by a ChromeVersionDataSource in order to
+ search the filesystem for the earliest existence of a specified API throughout
+ the different versions of Chrome; this constitutes an API's availability.
+ '''
+ class Factory(object):
+ def __init__(self,
+ chrome_version_utility,
+ object_store_creator_factory,
+ svn_file_system):
+ self._chrome_version_utility = chrome_version_utility
+ self._object_store_creator_factory = object_store_creator_factory
+ json_string = svn_file_system.ReadSingle('%s/api_availabilities.json'
+ % svn_constants.JSON_PATH)
+ self._existing_availabilities = json.loads(json_string)
+ json_string = svn_file_system.ReadSingle('%s/_permission_features.json'
+ % svn_constants.API_PATH)
+ self._permission_features = json.loads(json_comment_eater.Nom(
+ json_string))
+ json_string = svn_file_system.ReadSingle('%s/_manifest_features.json'
+ % svn_constants.API_PATH)
not at google - send to devlin 2013/04/30 18:34:19 use third_party.json_schema_compiler.json_parse as
epeterson 2013/05/13 02:38:10 Done.
+ self._manifest_features = json.loads(json_comment_eater.Nom(json_string))
+
+ def Create(self):
+ return AvailabilityDataSource(self._chrome_version_utility,
+ self._object_store_creator_factory,
+ self._existing_availabilities,
+ self._permission_features,
+ self._manifest_features)
+
+ def __init__(self,
+ chrome_version_utility,
+ object_store_creator_factory,
+ existing_availabilities,
+ permission_features,
+ manifest_features):
+ self._chrome_version_utility = chrome_version_utility
+ self._object_store_creator_factory = object_store_creator_factory
+ self._object_store = self._object_store_creator_factory.Create(
+ AvailabilityDataSource).Create()
+ self._existing_availabilities = existing_availabilities
+ self._permission_features = permission_features
+ self._manifest_features = manifest_features
+ self._permission_apis = []
+ self._manifest_apis = []
+ self._orphan_apis = []
+
+ def _CreateSvnFileSystemForBranch(self, branch):
not at google - send to devlin 2013/04/30 18:34:19 maybe this should go as a little helper on Subvers
epeterson 2013/05/13 02:38:10 Well, I had done this, and modified the old Create
+ '''Creates a file system tied to a specific |branch| of the svn repository.
+ '''
+ if branch == 'trunk':
+ svn_url = '/'.join((url_constants.SVN_TRUNK_URL,
+ 'src',
+ svn_constants.EXTENSIONS_PATH))
+ else:
+ svn_url = '/'.join((url_constants.SVN_BRANCH_URL,
+ branch,
+ 'src',
+ svn_constants.EXTENSIONS_PATH))
+ viewvc_url = svn_url.replace(url_constants.SVN_URL,
+ url_constants.VIEWVC_URL)
+
+ svn_file_system = CachingFileSystem(
+ SubversionFileSystem(AppEngineUrlFetcher(svn_url),
+ AppEngineUrlFetcher(viewvc_url)),
+ self._object_store_creator_factory)
+ return svn_file_system
+
+ def _GetChannelFromPermissionFeatures(self, api_name, permission_features):
+ '''Sometimes the API information will be in a dict, other times it will be
+ in a dict contained in a list.
+ '''
+ api_info = permission_features.get(api_name, None)
+ if api_info is not None:
+ try:
+ channel = api_info.get('channel')
+ except AttributeError:
+ channel = api_info[0].get('channel')
not at google - send to devlin 2013/04/30 18:34:19 don't use exceptions for control flow. Also, if it
epeterson 2013/05/13 02:38:10 Done.
+ finally:
+ return channel
+ return None
+
+ def _CheckStablePermissionExistence(self, api_name, version):
+ '''Checks _permission_features.json for the given |version| of Chrome,
+ and returns a boolean representing whether or not the API was available on
+ the stable channel in |version|.
+ '''
+ existence = self._object_store.Get('%s%s%s'
+ % (PERMISSION, api_name, version)).Get()
+ if existence is not None:
+ return existence
+
+ svn_file_system = self._object_store.Get('%s%s' % (SVN, version)).Get()
+ if svn_file_system is None:
+ svn_file_system = self._CreateSvnFileSystemForBranch(
+ self._chrome_version_utility.GetBranchNumberForVersion(version))
not at google - send to devlin 2013/04/30 18:34:19 I don't think you can put svn file systems in obje
epeterson 2013/05/13 02:38:10 Done.
+ self._object_store.Set('%s%s' % (SVN, version), svn_file_system)
+
+ json_string = svn_file_system.ReadSingle('%s/_permission_features.json'
+ % svn_constants.API_PATH)
+ permission_features = json.loads(json_comment_eater.Nom(json_string))
not at google - send to devlin 2013/04/30 18:34:19 same comment re json parsing i.e. use json_parse.P
epeterson 2013/05/13 02:38:10 Done.
+
+ existence = 'stable' == self._GetChannelFromPermissionFeatures(
+ api_name, permission_features)
+ self._object_store.Set('%s%s%s' % (PERMISSION, api_name, version),
+ existence)
+ return existence
+
+ def _CheckManifestExistence(self, api_name, version):
+ '''As a fallback measure for an API not being found in _permission_features,
+ check _manifest_features.json for the given |version| of Chrome,
+ and return a boolean representing whether or not the API was represented
+ within the file.
+ '''
+ #_manifest_features.json uses unix_hacker_style API names.
+ api_name = model.UnixName(api_name)
+ existence = self._object_store.Get('%s%s%s'
+ % (MANIFEST, api_name, version)).Get()
+ if existence is not None:
+ return existence
+
+ svn_file_system = self._object_store.Get('%s%s' % (SVN, version)).Get()
+ if svn_file_system is None:
+ svn_file_system = self._CreateSvnFileSystemForBranch(
+ self._chrome_version_utility.GetBranchNumberForVersion(version))
+ self._object_store.Set('%s%s' % (SVN, version), svn_file_system)
+
+ json_string = svn_file_system.ReadSingle('%s/_manifest_features.json'
+ % svn_constants.API_PATH)
+ manifest_features = json.loads(json_comment_eater.Nom(json_string))
+ if manifest_features.get(api_name, None) is not None:
+ existence = True
+ else:
+ existence = False
+ self._object_store.Set('%s%s%s' % (MANIFEST, api_name, version), existence)
+ return existence
not at google - send to devlin 2013/04/30 18:34:19 similar comments
epeterson 2013/05/13 02:38:10 Done.
+
+ def _GetAllNames(self, files_dict):
+ '''Returns extension-less names for a list of files.
+ '''
+ files = files_dict[svn_constants.API_PATH + '/']
+ return [model.UnixName(os.path.splitext(f)[0]) for f in files]
+
+ def _CheckFileSystemExistence(self, api_name, version):
+ '''Uses a list of API names for a given branch to check simply for the
+ existence of a given API in that branch.
+ '''
+ names = self._object_store.Get('%s%s' % (FILESYS, version)).Get()
+ if names is not None:
+ return api_name in names
+
+ svn_file_system = self._object_store.Get('%s%s' % (SVN, version)).Get()
+ if svn_file_system is None:
+ svn_file_system = self._CreateSvnFileSystemForBranch(
+ self._chrome_version_utility.GetBranchNumberForVersion(version))
+ self._object_store.Set('%s%s' % (SVN, version), svn_file_system)
+ names = svn_file_system.Read([svn_constants.API_PATH + '/']).Get()
+ names = self._GetAllNames(names)
+ self._object_store.Set('%s%s' % (FILESYS, version), names)
+ return api_name in names
not at google - send to devlin 2013/04/30 18:34:19 similar comments
epeterson 2013/05/13 02:38:10 Done.
+
+ def _FindEarliestStableAvailability(self, api_name, version):
+ '''Searches in descending order through filesystem caches tied to specific
+ chrome version numbers and looks for the availability of an API, |api_name|,
+ on the stable channel. When a version is found where the API is no longer
+ available on stable, returns the previous version number (the last known
+ version where the API was stable).
+ '''
+ # The _permission_features.json file (with 'channel' keys) is present only
+ # in Chrome 20 and onwards.
+ while version >= 20:
+ if ((api_name in self._permission_apis
+ and self._CheckStablePermissionExistence(api_name, str(version)))
+ or (api_name in self._manifest_apis
+ and self._CheckManifestExistence(api_name, str(version)))
+ or (api_name in self._orphan_apis
+ and self._CheckFileSystemExistence(api_name, str(version)))):
+ version -= 1
+ else:
+ break
+ version += 1
+ return str(version)
not at google - send to devlin 2013/04/30 18:34:19 return version + 1 rather than incrementing
epeterson 2013/05/13 02:38:10 Done.
+
+ def GetAvailability(self, api_name):
+ '''Determines the availability for an API by testing several scenarios.
+ (i.e. Is the API experimental? Only available on certain development
+ channels? If it's stable, when did it first become stable? etc.)
+ '''
+ availability = self._object_store.Get(api_name).Get()
+ if availability is not None:
+ return availability
+
+ # Check for a predetermined availability for this API.
+ availability = self._existing_availabilities.get(api_name, None)
not at google - send to devlin 2013/04/30 18:34:19 the None is implicit in get()
epeterson 2013/05/13 02:38:10 Done.
+ if availability is not None:
+ self._object_store.Set(api_name, availability)
+ return availability
+
+ latest_version = str(self._chrome_version_utility.GetLatestVersionNumber())
+ channel = self._GetChannelFromPermissionFeatures(api_name,
+ self._permission_features)
+ if channel is not None:
+ # This is a special case: availability can be any of the dev channels,
+ # to check for this information instead of checking just for existence.
+ availability = channel
+ self._permission_apis.append(api_name)
+ elif self._CheckManifestExistence(api_name, latest_version):
+ availability = 'stable'
+ self._manifest_apis.append(api_name)
+ elif self._CheckFileSystemExistence(api_name, latest_version):
+ availability = 'stable'
+ self._orphan_apis.append(api_name)
+ else:
+ logging.warning('%s could not be located. %s\'s availability is None.'
+ % (api_name, api_name))
+ availability = None
not at google - send to devlin 2013/04/30 18:34:19 throw a FileNotFoundError here or something, so we
epeterson 2013/05/13 02:38:10 Done.
+
+ if availability != 'stable':
+ self._object_store.Set(api_name, availability)
+ return availability
+
+ availability = self._FindEarliestStableAvailability(api_name,
+ int(latest_version) - 1)
+ self._object_store.Set(api_name, availability)
+ return availability
not at google - send to devlin 2013/04/30 18:34:19 slightly nicer factoring: if availability == 'sta
epeterson 2013/05/13 02:38:10 Done.

Powered by Google App Engine
This is Rietveld 408576698