Chromium Code Reviews| 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 import os | 5 import os |
| 6 | 6 |
| 7 from third_party.json_schema_compiler.json_parse import Parse | |
| 7 import third_party.json_schema_compiler.model as model | 8 import third_party.json_schema_compiler.model as model |
| 8 import docs_server_utils as utils | 9 import docs_server_utils as utils |
| 9 | 10 |
| 10 class APIListDataSource(object): | 11 class APIListDataSource(object): |
| 11 """ This class creates a list of chrome.* APIs and chrome.experimental.* APIs | 12 """ This class creates a list of chrome.* APIs and chrome.experimental.* APIs |
| 12 for extensions and apps that are used in the api_index.html and | 13 for extensions and apps that are used in the api_index.html and |
| 13 experimental.html pages. | 14 experimental.html pages. |
| 14 |api_path| is the path to the API schemas. | 15 |file_system| is the host file system. |
| 15 |public_path| is the path to the public HTML templates. | 16 |public_template_path| is the relative path to public API HTML templates. |
| 16 An API is considered listable if it's in both |api_path| and |public_path| - | 17 |api_features_path| is the path to _api_features.json. |
| 17 the API schemas may contain undocumentable APIs, and the public HTML templates | 18 |manifest_features_path| is the path to _manifest_features.json. |
| 18 will contain non-API articles. | 19 |permission_features_path| is the path to _permission_features.json. |
| 20 | |
| 21 An API is considered listable if it is listed in _api_features.json, | |
| 22 it has a corresponding HTML file in the public template path, and one of | |
| 23 the following conditions is met: | |
| 24 - It has no "dependencies" or "extension_types" properties in _api_features | |
| 25 - It has an "extension_types" property in _api_features with either/both | |
| 26 "extension"/"platform_app" values present. | |
| 27 - It has a dependency in _{api,manifest,permission}_features with an | |
| 28 "extension_types" property where either/both "extension"/"platform_app" | |
| 29 values are present. | |
| 19 """ | 30 """ |
| 20 class Factory(object): | 31 class Factory(object): |
| 21 def __init__(self, compiled_fs_factory, file_system, api_path, public_path): | 32 def __init__(self, |
| 22 self._compiled_fs = compiled_fs_factory.Create(self._ListAPIs, | 33 file_system, |
| 23 APIListDataSource) | 34 public_template_path, |
| 35 api_features_path, | |
| 36 manifest_features_path, | |
| 37 permission_features_path): | |
| 24 self._file_system = file_system | 38 self._file_system = file_system |
| 25 def Normalize(string): | 39 def NormalizePath(string): |
| 26 return string if string.endswith('/') else (string + '/') | 40 return string if string.endswith('/') else (string + '/') |
| 27 self._api_path = Normalize(api_path) | 41 self._public_template_path = NormalizePath(public_template_path) |
| 28 self._public_path = Normalize(public_path) | 42 self._api_features = Parse(file_system.ReadSingle(api_features_path)) |
| 43 self._manifest_features = Parse( | |
| 44 file_system.ReadSingle(manifest_features_path)) | |
| 45 self._permission_features = Parse( | |
| 46 file_system.ReadSingle(permission_features_path)) | |
|
not at google - send to devlin
2013/09/19 19:21:52
It's preferable to do heavy lifting outside constr
| |
| 47 self._public_apis = { | |
| 48 'apps': self._GetPublicAPIs('apps'), | |
| 49 'extensions': self._GetPublicAPIs('extensions') | |
| 50 } | |
| 51 self._apis = self._GenerateAPIDict() | |
| 29 | 52 |
| 30 def _GetAPIsInSubdirectory(self, api_names, doc_type): | 53 def _GetPublicAPIs(self, platform): |
| 31 public_templates = [] | 54 public_templates = [] |
| 32 for root, _, files in self._file_system.Walk( | 55 for root, _, files in self._file_system.Walk( |
| 33 self._public_path + doc_type): | 56 self._public_template_path + platform): |
| 34 public_templates.extend( | 57 public_templates.extend( |
| 35 ('%s/%s' % (root, name)).lstrip('/') for name in files) | 58 ('%s/%s' % (root, name)).lstrip('/') for name in files) |
| 36 template_names = set(os.path.splitext(name)[0] | 59 template_names = set(os.path.splitext(name)[0] |
| 37 for name in public_templates) | 60 for name in public_templates) |
| 38 experimental_apis = [] | 61 return map(lambda name: name.replace('_', '.'), template_names) |
| 39 chrome_apis = [] | 62 |
| 40 private_apis = [] | 63 def _GetExtensionTypesForDependency(self, dependency): |
| 41 for template_name in sorted(template_names): | 64 feature_sources = { |
| 42 if model.UnixName(template_name) not in api_names: | 65 'api': self._api_features, |
| 43 continue | 66 'manifest': self._manifest_features, |
| 44 entry = {'name': template_name.replace('_', '.')} | 67 'permission': self._permission_features |
| 45 if template_name.startswith('experimental'): | |
| 46 experimental_apis.append(entry) | |
| 47 elif template_name.endswith('Private'): | |
| 48 private_apis.append(entry) | |
| 49 else: | |
| 50 chrome_apis.append(entry) | |
| 51 if len(chrome_apis): | |
| 52 chrome_apis[-1]['last'] = True | |
| 53 if len(experimental_apis): | |
| 54 experimental_apis[-1]['last'] = True | |
| 55 if len(private_apis): | |
| 56 private_apis[-1]['last'] = True | |
| 57 return { | |
| 58 'chrome': chrome_apis, | |
| 59 'experimental': experimental_apis, | |
| 60 'private': private_apis | |
| 61 } | 68 } |
| 69 feature_type, feature_name = dependency.split(':') | |
|
not at google - send to devlin
2013/09/19 19:21:52
This is the sort of stuff that feature_utility c/s
| |
| 70 feature = feature_sources[feature_type].get(feature_name, None) | |
| 71 if feature is None: | |
| 72 logging.error('Unable to resolve feature dependency %s' % dependency) | |
| 73 return [] | |
| 74 if type(feature) is list: | |
|
not at google - send to devlin
2013/09/19 19:21:52
isinstance(feature, list):
but again feature_util
| |
| 75 extension_types = [] | |
| 76 for branch in feature: | |
| 77 extension_types.extend(branch.get('extension_types', [])) | |
| 78 else: | |
| 79 extension_types = feature.get('extension_types', []) | |
| 80 return extension_types | |
| 62 | 81 |
| 63 def _ListAPIs(self, base_dir, apis): | 82 def _GetAPIPlatforms(self, api): |
| 64 api_names = set(utils.SanitizeAPIName(name) for name in apis) | 83 def MapExtensionTypesToAPIPlatforms(extension_types): |
| 65 return { | 84 mapping = { 'extension': 'extensions', 'platform_app': 'apps' } |
| 66 'apps': self._GetAPIsInSubdirectory(api_names, 'apps'), | 85 platforms = set() |
| 67 'extensions': self._GetAPIsInSubdirectory(api_names, 'extensions') | 86 for extension_type in extension_types: |
| 87 if extension_type in mapping: | |
| 88 platforms.add(mapping[extension_type]) | |
| 89 return platforms | |
| 90 extension_types = api.get('extension_types', None) | |
| 91 if extension_types is not None: | |
| 92 return MapExtensionTypesToAPIPlatforms(extension_types) | |
| 93 platforms = set(['apps', 'extensions']) | |
|
not at google - send to devlin
2013/09/19 19:21:52
when creating fixed-length lists use (...) not [..
Ken Rockot(use gerrit already)
2013/09/20 20:53:37
Done.
| |
| 94 for dependency in api.get('dependencies', []): | |
|
not at google - send to devlin
2013/09/19 19:21:52
() not []
Ken Rockot(use gerrit already)
2013/09/20 20:53:37
Done.
| |
| 95 platforms = platforms.intersection(MapExtensionTypesToAPIPlatforms( | |
| 96 self._GetExtensionTypesForDependency(dependency))) | |
| 97 return list(platforms) | |
| 98 | |
| 99 def _GetAPICategory(self, api, platform): | |
| 100 name = api['name'] | |
| 101 if name.startswith('experimental.'): | |
| 102 return 'experimental' | |
| 103 elif (name.endswith('Private') or | |
| 104 name not in self._public_apis[platform]): | |
| 105 return 'private' | |
| 106 else: | |
| 107 return 'chrome' | |
|
not at google - send to devlin
2013/09/19 19:21:52
no else's after return's.
Ken Rockot(use gerrit already)
2013/09/20 20:53:37
Done.
| |
| 108 | |
| 109 def _GenerateAPIDict(self): | |
| 110 def MakeEmptyAPIDict(): | |
| 111 return { 'chrome': [], 'experimental': [], 'private': [] } | |
| 112 api_dict = { | |
| 113 'apps': MakeEmptyAPIDict(), | |
| 114 'extensions': MakeEmptyAPIDict() | |
| 68 } | 115 } |
| 116 for (name, api) in self._api_features.items(): | |
|
not at google - send to devlin
2013/09/19 19:21:52
name, api not (name, api)
iteritems not items.
Ken Rockot(use gerrit already)
2013/09/20 20:53:37
Done.
| |
| 117 api['name'] = name | |
| 118 for platform in self._GetAPIPlatforms(api): | |
| 119 api_dict[platform][self._GetAPICategory(api, platform)].append(api) | |
| 120 for platform in api_dict.keys(): | |
|
not at google - send to devlin
2013/09/19 19:21:52
iterkeys
Ken Rockot(use gerrit already)
2013/09/20 20:53:37
Done.
| |
| 121 for category in api_dict[platform]: | |
| 122 api_dict[platform][category][-1]['last'] = True | |
| 123 return api_dict | |
| 69 | 124 |
| 70 def Create(self): | 125 def Create(self): |
| 71 return APIListDataSource(self._compiled_fs, self._api_path) | 126 return APIListDataSource(self._apis) |
| 72 | 127 |
| 73 def __init__(self, compiled_fs, api_path): | 128 def __init__(self, apis): |
| 74 self._compiled_fs = compiled_fs | 129 self._apis = apis |
| 75 self._api_path = api_path | |
| 76 | 130 |
| 77 def GetAllNames(self): | 131 def GetAllNames(self): |
| 78 names = [] | 132 apis = [] |
| 79 for platform in ['apps', 'extensions']: | 133 for platform in ['apps', 'extensions']: |
| 80 for category in ['chrome', 'experimental', 'private']: | 134 for category in ['chrome', 'experimental', 'private']: |
| 81 names.extend(self.get(platform).get(category)) | 135 apis.extend(self._apis[platform][category]) |
| 82 return [api_name['name'] for api_name in names] | 136 return [api['name'] for api in apis] |
| 83 | 137 |
| 84 def get(self, key): | 138 def get(self, key): |
| 85 return self._compiled_fs.GetFromFileListing(self._api_path)[key] | 139 return self._apis.get(key) |
| OLD | NEW |