Chromium Code Reviews| 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..4b63b90c297254c8f4917c78897e1bfd1e10f365 |
| --- /dev/null |
| +++ b/chrome/common/extensions/docs/server2/availability_data_source.py |
| @@ -0,0 +1,142 @@ |
| +# 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 os |
| + |
| +from appengine_url_fetcher import AppEngineUrlFetcher |
| +from caching_file_system import CachingFileSystem |
| +from compiled_file_system import CompiledFileSystem |
| +from object_store_creator import ObjectStoreCreator |
| +from subversion_file_system import SubversionFileSystem |
| +import svn_constants |
| +import third_party.json_schema_compiler.model as model |
| +import url_constants |
| + |
|
epeterson
2013/04/17 03:38:50
Removed the [huge] dependency on api_data_source f
|
| +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, svn_file_system=None): |
| + self._chrome_version_utility = chrome_version_utility |
| + self._object_store = ObjectStoreCreator(AvailabilityDataSource).Create() |
| + |
| + # The |svn_file_system| will only be none for testing. |
| + if svn_file_system is not None: |
| + json_string = svn_file_system.ReadSingle('%s/api_availabilities.json' |
| + % svn_constants.JSON_PATH) |
| + self._existing_availabilities = json.loads(json_string) |
| + |
|
epeterson
2013/04/17 03:38:50
This hasn't been tested on the appengine, because
|
| + def Create(self): |
| + return AvailabilityDataSource(self._chrome_version_utility, |
| + self._object_store, |
| + self._existing_availabilities) |
| + |
| + def __init__(self, |
| + chrome_version_utility, |
| + object_store, |
| + existing_availabilities): |
| + self._chrome_version_utility = chrome_version_utility |
| + self._object_store = object_store |
| + self._existing_availabilities = existing_availabilities |
| + |
| + def _CreateSvnFileSystemForBranch(self, branch): |
| + '''Creates a file system tied to a 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)), |
| + ObjectStoreCreator.Factory(branch)) |
| + return svn_file_system |
| + |
| + def _GetAllNames(self, base_dir, apis): |
| + '''Returns unix_hacker_style names for all APIs currently available. |
| + ''' |
| + return [ |
| + model.UnixName(os.path.splitext(api)[0]) |
| + for api in apis |
| + ] |
| + |
| + def _GetAsSubdirectory(self, name): |
| + if name.startswith('experimental_'): |
| + parts = name[len('experimental_'):].split('_', 1) |
| + if len(parts) > 1: |
| + parts[1] = 'experimental_%s' % parts[1] |
| + return '/'.join(parts) |
| + else: |
| + return '%s/%s' % (parts[0], name) |
| + return name.replace('_', '/', 1) |
| + |
| + def _CheckApiExistence(self, api_name, version): |
| + '''Finds a list of APIs that are present in the given |version|, and checks |
| + to see whether or not |api_name| exists in that list. |
| + ''' |
| + names = self._object_store.Get(version).Get() |
| + |
| + if names is None: |
| + svn_file_system = self._CreateSvnFileSystemForBranch( |
| + self._chrome_version_utility.GetBranchNumberForVersion(version)) |
| + compiled_fs_factory = CompiledFileSystem.Factory( |
| + svn_file_system, |
| + ObjectStoreCreator.Factory()) |
| + names_cache = compiled_fs_factory.Create(self._GetAllNames, |
| + AvailabilityDataSource) |
| + names = names_cache.GetFromFileListing(svn_constants.API_PATH) |
|
epeterson
2013/04/17 03:38:50
Instead of trying to load every file and check for
|
| + self._object_store.Set(version, names) |
| + api_name = model.UnixName(api_name) |
| + return api_name in names or self._GetAsSubdirectory(api_name) in names |
| + |
| + def FindEarliestAvailability(self, api_name): |
| + '''Searches in descending order through filesystem caches tied to specific |
| + chrome version numbers and looks for the existence of a specified api, |
| + |api_name|. When an api is not found, returns the previous version number |
| + (the last known version where the api was found). |
| + ''' |
| + availability = self._object_store.Get(api_name).Get() |
| + if availability is not None: |
| + return availability |
| + elif availability is False: |
| + return None |
| + |
| + # Check for a predetermined availability for this API. |
| + availability = self._existing_availabilities.get(api_name, None) |
| + if availability is not None: |
| + self._object_store.Set(api_name, availability) |
| + return availability |
| + |
| + # If the API isn't found in trunk, then it isn't currently available. |
| + if not self._CheckApiExistence(api_name, 'trunk'): |
| + self._object_store.Set(api_name, False) |
| + return None |
| + |
| + latest_version = int(self._chrome_version_utility.GetLatestVersionNumber()) |
| + version_int = latest_version |
| + # Extension APIs are not present in the filesystem before version 18. |
| + while version_int >= 18: |
| + if not self._CheckApiExistence(api_name, str(version_int)): |
| + break |
| + version_int -= 1 |
| + |
| + version_int += 1 |
| + if version_int > latest_version: |
| + availability = 'trunk' |
| + else: |
| + availability = str(version_int) |
| + |
| + self._object_store.Set(api_name, availability) |
| + return availability |