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

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

Issue 25627002: Docserver: when checking for the existence of an API on a branch, just look at (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: revert some unnecessary stuff Created 7 years, 2 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 | Annotate | Revision Log
OLDNEW
1 # Copyright 2013 The Chromium Authors. All rights reserved. 1 # Copyright 2013 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 collections 5 from collections import Mapping
6 import os 6 import os
7 7
8 from api_schema_graph import APISchemaGraph 8 from api_schema_graph import APISchemaGraph
9 from branch_utility import BranchUtility 9 from branch_utility import BranchUtility
10 from compiled_file_system import CompiledFileSystem 10 from compiled_file_system import CompiledFileSystem
11 from svn_constants import API_PATH 11 from svn_constants import API_PATH
12 from third_party.json_schema_compiler import idl_schema, idl_parser, json_parse 12 from third_party.json_schema_compiler import idl_schema, idl_parser, json_parse
13 from third_party.json_schema_compiler.json_parse import OrderedDict 13 from third_party.json_schema_compiler.json_parse import OrderedDict
14 from third_party.json_schema_compiler.model import UnixName 14 from third_party.json_schema_compiler.model import UnixName
15 15
16 16
17 _EXTENSION_API = 'extension_api.json' 17 _EXTENSION_API = 'extension_api.json'
18 18
19 19
20 def _GetChannelFromFeatures(api_name, file_system, path): 20 def _GetChannelFromFeatures(api_name, file_system, path):
21 '''Finds API channel information within _features.json files at the given 21 '''Finds API channel information within _features.json files at the given
22 |path| for the given |file_system|. Returns None if channel information for 22 |path| for the given |file_system|. Returns None if channel information for
23 the API cannot be located. 23 the API cannot be located.
24 ''' 24 '''
25 feature = file_system.GetFromFile(path).get(api_name) 25 feature = file_system.GetFromFile(path).get(api_name)
26 26
27 if feature is None: 27 if feature is None:
28 return None 28 return None
29 if isinstance(feature, collections.Mapping): 29 if isinstance(feature, Mapping):
30 # The channel information exists as a solitary dict. 30 # The channel information exists as a solitary dict.
31 return feature.get('channel') 31 return feature.get('channel')
32 # The channel information dict is nested within a list for whitelisting 32 # The channel information dict is nested within a list for whitelisting
33 # purposes. Take the newest channel out of all of the entries. 33 # purposes. Take the newest channel out of all of the entries.
34 return BranchUtility.NewestChannel(entry.get('channel') for entry in feature) 34 return BranchUtility.NewestChannel(entry.get('channel') for entry in feature)
35 35
36 36
37 def _GetChannelFromApiFeatures(api_name, file_system): 37 def _GetChannelFromApiFeatures(api_name, file_system):
38 return _GetChannelFromFeatures( 38 return _GetChannelFromFeatures(
39 api_name, 39 api_name,
40 file_system, 40 file_system,
41 '%s/_api_features.json' % API_PATH) 41 '%s/_api_features.json' % API_PATH)
42 42
43 43
44 def _GetChannelFromManifestFeatures(api_name, file_system): 44 def _GetChannelFromManifestFeatures(api_name, file_system):
45 return _GetChannelFromFeatures( 45 return _GetChannelFromFeatures(
46 UnixName(api_name), #_manifest_features uses unix_style API names 46 UnixName(api_name), #_manifest_features uses unix_style API names
47 file_system, 47 file_system,
48 '%s/_manifest_features.json' % API_PATH) 48 '%s/_manifest_features.json' % API_PATH)
49 49
50 50
51 def _GetChannelFromPermissionFeatures(api_name, file_system): 51 def _GetChannelFromPermissionFeatures(api_name, file_system):
52 return _GetChannelFromFeatures( 52 return _GetChannelFromFeatures(
53 api_name, 53 api_name,
54 file_system, 54 file_system,
55 '%s/_permission_features.json' % API_PATH) 55 '%s/_permission_features.json' % API_PATH)
56 56
57 57
58 def _GetApiSchemaFilename(api_name, file_system):
59 '''Gets the name of the file which contains the schema for |api_name| in
60 |file_system|, or None if the API is not found. Note that this may be the
61 single _EXTENSION_API file which all APIs share in older versions of Chrome.
62 '''
63 def under_api_path(path):
64 return '%s/%s' % (API_PATH, path)
65
66 file_names = file_system.ReadSingle(under_api_path(''))
67
68 if _EXTENSION_API in file_names:
69 # Prior to Chrome version 18, extension_api.json contained all API schema
Jeffrey Yasskin 2013/10/02 00:19:17 Do we still need this code?
not at google - send to devlin 2013/10/02 00:40:02 Yes, this is the class responsible for stepping ba
70 # data, which replaced the current implementation of individual API files.
71 # We're forced to parse this (very large) file to determine if the API
72 # exists in it.
73 #
74 # TODO(epeterson) Avoid doing unnecessary work by re-parsing.
75 # See http://crbug.com/295812.
76 extension_api_json = json_parse.Parse(
77 file_system.ReadSingle('%s/%s'% (API_PATH, _EXTENSION_API)))
78 if any(api['namespace'] == api_name for api in extension_api_json):
79 return under_api_path(_EXTENSION_API)
80 return None
81
82 api_file_names = [
83 file_name for file_name in file_names
84 if os.path.splitext(file_name)[0] in (api_name, UnixName(api_name))]
85 assert len(api_file_names) < 2
86 return under_api_path(api_file_names[0]) if api_file_names else None
87
88
58 def _GetApiSchema(api_name, file_system): 89 def _GetApiSchema(api_name, file_system):
59 '''Searches |file_system| for |api_name|'s API schema data, and parses and 90 '''Searches |file_system| for |api_name|'s API schema data, and parses and
60 returns it if found. 91 returns it if found.
61 ''' 92 '''
62 file_names = file_system.ReadSingle('%s/' % API_PATH) 93 api_file_name = _GetApiSchemaFilename(api_name, file_system)
63 # API names can be represented in unix_style and camelCase formats. 94 if api_file_name is None:
64 possibilities = (api_name, UnixName(api_name)) 95 return None
65 96
66 def get_file_data(file_name): 97 api_file_text = file_system.ReadSingle(api_file_name)
67 return file_system.ReadSingle('%s/%s' % (API_PATH, file_name)) 98 if api_file_name == _EXTENSION_API:
68 99 return [api for api in json_parse.Parse(api_file_text)
69 if _EXTENSION_API in file_names: 100 if api['namespace'] == api_name][0]
Jeffrey Yasskin 2013/10/02 00:19:17 It looks like the old code would return None if th
not at google - send to devlin 2013/10/02 00:40:02 It still does return None; _GetApiSchemaFilename w
70 # Prior to Chrome version 18, extension_api.json contained all API schema 101 if api_file_name.endswith('.idl'):
71 # data, which replaced the current implementation of individual API files. 102 return idl_parser.IDLParser().ParseData(api_file_text)
72 # 103 return json_parse.Parse(api_file_text) # [0]?
Jeffrey Yasskin 2013/10/02 00:19:17 Figure out the "[0]?" before checking this in.
not at google - send to devlin 2013/10/02 00:40:02 Done.
73 # TODO(epeterson) This file will be parsed a lot, but the data remains the
74 # same for each API. Avoid doing unnecessary work by re-parsing.
75 # (see http://crbug.com/295812)
76 extension_api_json = json_parse.Parse(get_file_data(_EXTENSION_API))
77 api = [api for api in extension_api_json if api['namespace'] == api_name]
78 return api if api else None
79
80 def check_file(file_name):
81 return os.path.splitext(file_name)[0] in (api_name, UnixName(api_name))
82
83 for file_name in file_names:
84 if check_file(file_name):
85 if file_name.endswith('idl'):
86 idl_data = idl_parser.IDLParser().ParseData(get_file_data(file_name))
87 return idl_schema.IDLSchema(idl_data).process()
88 return json_parse.Parse(get_file_data(file_name))
89 return None
90 104
91 105
92 class AvailabilityFinder(object): 106 class AvailabilityFinder(object):
93 '''Generates availability information for APIs by looking at API schemas and 107 '''Generates availability information for APIs by looking at API schemas and
94 _features files over multiple release versions of Chrome. 108 _features files over multiple release versions of Chrome.
95 ''' 109 '''
96 110
97 def __init__(self, 111 def __init__(self,
98 file_system_iterator, 112 file_system_iterator,
99 object_store_creator, 113 object_store_creator,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 # found using _api_features.json. 146 # found using _api_features.json.
133 available_channel = available_channel or ( 147 available_channel = available_channel or (
134 _GetChannelFromPermissionFeatures(api_name, features_fs) 148 _GetChannelFromPermissionFeatures(api_name, features_fs)
135 or _GetChannelFromManifestFeatures(api_name, features_fs)) 149 or _GetChannelFromManifestFeatures(api_name, features_fs))
136 if available_channel is not None: 150 if available_channel is not None:
137 return available_channel == 'stable' 151 return available_channel == 'stable'
138 if version >= 5: 152 if version >= 5:
139 # Fall back to a check for file system existence if the API is not 153 # Fall back to a check for file system existence if the API is not
140 # stable in any of the _features.json files, or if the _features files 154 # stable in any of the _features.json files, or if the _features files
141 # do not exist (version 19 and earlier). 155 # do not exist (version 19 and earlier).
142 return _GetApiSchema(api_name, file_system) is not None 156 return _GetApiSchemaFilename(api_name, file_system) is not None
Jeffrey Yasskin 2013/10/02 00:19:17 Replace these with "ApiExists(api_name, file_syste
not at google - send to devlin 2013/10/02 00:40:02 Done.
143 157
144 def _CheckChannelAvailability(self, api_name, file_system, channel_name): 158 def _CheckChannelAvailability(self, api_name, file_system, channel_name):
145 '''Searches through the _features files in a given |file_system| and 159 '''Searches through the _features files in a given |file_system| and
146 determines whether or not an API is available on the given channel, 160 determines whether or not an API is available on the given channel,
147 |channel_name|. 161 |channel_name|.
148 ''' 162 '''
149 fs_factory = CompiledFileSystem.Factory(file_system, 163 fs_factory = CompiledFileSystem.Factory(file_system,
150 self._object_store_creator) 164 self._object_store_creator)
151 features_fs = fs_factory.Create(lambda _, json: json_parse.Parse(json), 165 features_fs = fs_factory.Create(lambda _, json: json_parse.Parse(json),
152 AvailabilityFinder, 166 AvailabilityFinder,
153 category='features') 167 category='features')
154 available_channel = (_GetChannelFromApiFeatures(api_name, features_fs) 168 available_channel = (_GetChannelFromApiFeatures(api_name, features_fs)
155 or _GetChannelFromPermissionFeatures(api_name, features_fs) 169 or _GetChannelFromPermissionFeatures(api_name, features_fs)
156 or _GetChannelFromManifestFeatures(api_name, features_fs)) 170 or _GetChannelFromManifestFeatures(api_name, features_fs))
157 if (available_channel is None and 171 if (available_channel is None and
158 _GetApiSchema(api_name, file_system) is not None): 172 _GetApiSchemaFilename(api_name, file_system) is not None):
159 # If an API is not represented in any of the _features files, but exists 173 # If an API is not represented in any of the _features files, but exists
160 # in the filesystem, then assume it is available in this version. 174 # in the filesystem, then assume it is available in this version.
161 # The windows API is an example of this. 175 # The windows API is an example of this.
162 available_channel = channel_name 176 available_channel = channel_name
163 # If the channel we're checking is the same as or newer than the 177 # If the channel we're checking is the same as or newer than the
164 # |available_channel| then the API is available at this channel. 178 # |available_channel| then the API is available at this channel.
165 return (available_channel is not None and 179 return (available_channel is not None and
166 BranchUtility.NewestChannel((available_channel, channel_name)) 180 BranchUtility.NewestChannel((available_channel, channel_name))
167 == channel_name) 181 == channel_name)
168 182
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 return availability 215 return availability
202 216
203 def GetApiNodeAvailability(self, api_name): 217 def GetApiNodeAvailability(self, api_name):
204 '''Returns an APISchemaGraph annotated with each node's availability (the 218 '''Returns an APISchemaGraph annotated with each node's availability (the
205 ChannelInfo at the oldest channel it's available in). 219 ChannelInfo at the oldest channel it's available in).
206 ''' 220 '''
207 availability_graph = self._node_level_object_store.Get(api_name).Get() 221 availability_graph = self._node_level_object_store.Get(api_name).Get()
208 if availability_graph is not None: 222 if availability_graph is not None:
209 return availability_graph 223 return availability_graph
210 224
225
211 availability_graph = APISchemaGraph() 226 availability_graph = APISchemaGraph()
212 trunk_graph = APISchemaGraph(_GetApiSchema(api_name, 227 trunk_graph = APISchemaGraph(_GetApiSchema(api_name,
213 self._host_file_system)) 228 self._host_file_system))
214 def update_availability_graph(file_system, channel_info): 229 def update_availability_graph(file_system, channel_info):
215 version_graph = APISchemaGraph(_GetApiSchema(api_name, file_system)) 230 version_graph = APISchemaGraph(_GetApiSchema(api_name, file_system))
216 # Keep track of any new schema elements from this version by adding 231 # Keep track of any new schema elements from this version by adding
217 # them to |availability_graph|. 232 # them to |availability_graph|.
218 # 233 #
219 # Calling |availability_graph|.Lookup() on the nodes being updated 234 # Calling |availability_graph|.Lookup() on the nodes being updated
220 # will return the |annotation| object. 235 # will return the |annotation| object.
221 availability_graph.Update(version_graph.Subtract(availability_graph), 236 availability_graph.Update(version_graph.Subtract(availability_graph),
222 annotation=channel_info) 237 annotation=channel_info)
223 238
224 # Continue looping until there are no longer differences between this 239 # Continue looping until there are no longer differences between this
225 # version and trunk. 240 # version and trunk.
226 return trunk_graph != version_graph 241 return trunk_graph != version_graph
227 242
228 self._file_system_iterator.Ascending( 243 self._file_system_iterator.Ascending(self.GetApiAvailability(api_name),
229 self.GetApiAvailability(api_name), 244 update_availability_graph)
230 update_availability_graph)
231 245
232 self._node_level_object_store.Set(api_name, availability_graph) 246 self._node_level_object_store.Set(api_name, availability_graph)
233 return availability_graph 247 return availability_graph
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698