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

Side by Side Diff: chrome/common/extensions/docs/server2/handler.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: Fixing issues with experimental_APIs 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 unified diff | Download patch
OLDNEW
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 logging 5 import logging
6 import os 6 import os
7 from StringIO import StringIO 7 from StringIO import StringIO
8 import sys 8 import sys
9 9
10 from appengine_wrappers import webapp 10 from appengine_wrappers import webapp
11 from appengine_wrappers import memcache 11 from appengine_wrappers import memcache
12 from appengine_wrappers import urlfetch 12 from appengine_wrappers import urlfetch
13 13
14 from api_data_source import APIDataSource 14 from api_data_source import APIDataSource
15 from api_list_data_source import APIListDataSource 15 from api_list_data_source import APIListDataSource
16 from appengine_blobstore import AppEngineBlobstore 16 from appengine_blobstore import AppEngineBlobstore
17 from in_memory_object_store import InMemoryObjectStore
18 from appengine_url_fetcher import AppEngineUrlFetcher 17 from appengine_url_fetcher import AppEngineUrlFetcher
18 from availability_data_source import AvailabilityDataSource
19 from branch_utility import BranchUtility 19 from branch_utility import BranchUtility
20 from example_zipper import ExampleZipper 20 from chrome_version_data_source import ChromeVersionDataSource
21 from compiled_file_system import CompiledFileSystem 21 from compiled_file_system import CompiledFileSystem
22 import compiled_file_system as compiled_fs 22 import compiled_file_system as compiled_fs
23 from example_zipper import ExampleZipper
23 from github_file_system import GithubFileSystem 24 from github_file_system import GithubFileSystem
25 from in_memory_object_store import InMemoryObjectStore
24 from intro_data_source import IntroDataSource 26 from intro_data_source import IntroDataSource
25 from known_issues_data_source import KnownIssuesDataSource 27 from known_issues_data_source import KnownIssuesDataSource
26 from local_file_system import LocalFileSystem 28 from local_file_system import LocalFileSystem
27 from memcache_file_system import MemcacheFileSystem 29 from memcache_file_system import MemcacheFileSystem
28 from reference_resolver import ReferenceResolver 30 from reference_resolver import ReferenceResolver
29 from samples_data_source import SamplesDataSource 31 from samples_data_source import SamplesDataSource
30 from server_instance import ServerInstance 32 from server_instance import ServerInstance
31 from sidenav_data_source import SidenavDataSource 33 from sidenav_data_source import SidenavDataSource
32 from subversion_file_system import SubversionFileSystem 34 from subversion_file_system import SubversionFileSystem
33 from template_data_source import TemplateDataSource 35 from template_data_source import TemplateDataSource
34 from third_party.json_schema_compiler.model import UnixName 36 from third_party.json_schema_compiler.model import UnixName
35 import url_constants 37 import url_constants
36 38
37 # Increment this version to force the server to reload all pages in the first 39 # Increment this version to force the server to reload all pages in the first
38 # cron job that is run. 40 # cron job that is run.
39 _VERSION = 1 41 _VERSION = 2
40 42
41 # The default channel to serve docs for if no channel is specified. 43 # The default channel to serve docs for if no channel is specified.
42 _DEFAULT_CHANNEL = 'stable' 44 _DEFAULT_CHANNEL = 'stable'
43 45
44 BRANCH_UTILITY_MEMCACHE = InMemoryObjectStore('branch_utility') 46 BRANCH_UTILITY_MEMCACHE = InMemoryObjectStore('branch_utility')
45 BRANCH_UTILITY = BranchUtility(url_constants.OMAHA_PROXY_URL, 47 BRANCH_UTILITY = BranchUtility(url_constants.OMAHA_PROXY_URL,
46 AppEngineUrlFetcher(None), 48 AppEngineUrlFetcher(None),
47 BRANCH_UTILITY_MEMCACHE) 49 BRANCH_UTILITY_MEMCACHE)
48 50
51 AVAILABILITY_DATA_SOURCE_MEMCACHE = InMemoryObjectStore(
52 'availability_data_source')
53
49 GITHUB_MEMCACHE = InMemoryObjectStore('github') 54 GITHUB_MEMCACHE = InMemoryObjectStore('github')
50 GITHUB_FILE_SYSTEM = GithubFileSystem( 55 GITHUB_FILE_SYSTEM = GithubFileSystem(
51 AppEngineUrlFetcher(url_constants.GITHUB_URL), 56 AppEngineUrlFetcher(url_constants.GITHUB_URL),
52 GITHUB_MEMCACHE, 57 GITHUB_MEMCACHE,
53 AppEngineBlobstore()) 58 AppEngineBlobstore())
54 GITHUB_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory(GITHUB_FILE_SYSTEM, 59 GITHUB_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory(GITHUB_FILE_SYSTEM,
55 GITHUB_MEMCACHE) 60 GITHUB_MEMCACHE)
56 61
57 EXTENSIONS_PATH = 'chrome/common/extensions' 62 EXTENSIONS_PATH = 'chrome/common/extensions'
58 DOCS_PATH = 'docs' 63 DOCS_PATH = 'docs'
(...skipping 18 matching lines...) Expand all
77 return [UnixName(os.path.splitext(f.split('/')[-1])[0]) for f in files] 82 return [UnixName(os.path.splitext(f.split('/')[-1])[0]) for f in files]
78 83
79 def _CreateMemcacheFileSystem(branch, branch_memcache): 84 def _CreateMemcacheFileSystem(branch, branch_memcache):
80 svn_url = _GetURLFromBranch(branch) + '/' + EXTENSIONS_PATH 85 svn_url = _GetURLFromBranch(branch) + '/' + EXTENSIONS_PATH
81 stat_fetcher = AppEngineUrlFetcher( 86 stat_fetcher = AppEngineUrlFetcher(
82 svn_url.replace(url_constants.SVN_URL, url_constants.VIEWVC_URL)) 87 svn_url.replace(url_constants.SVN_URL, url_constants.VIEWVC_URL))
83 fetcher = AppEngineUrlFetcher(svn_url) 88 fetcher = AppEngineUrlFetcher(svn_url)
84 return MemcacheFileSystem(SubversionFileSystem(fetcher, stat_fetcher), 89 return MemcacheFileSystem(SubversionFileSystem(fetcher, stat_fetcher),
85 branch_memcache) 90 branch_memcache)
86 91
87 _default_branch = BRANCH_UTILITY.GetBranchNumberForChannelName(_DEFAULT_CHANNEL) 92 def _CreateAPIDataSourceForBranch(branch_number):
93 return _CreateObjectsForBranch(branch_number, None)
94
95 def _CreateInstanceForBranch(branch_number, channel_info):
96 return _CreateObjectsForBranch(branch_number, channel_info)
97
98 def _CreateObjectsForBranch(branch_number, channel_info=None):
99 """Passed to the global instance of chrome_version_data_source, and also used
100 in _GetInstanceForBranch. Allows for the creation of api_data_sources linked
101 to |branch_number|, which is the maximum branch number from a given version of
102 chrome, and the creation of a branch instance.
103 """
104 channel_name = _DEFAULT_CHANNEL
105 availability_data_source = None
106 instance = None
107
108 if channel_info is not None:
109 channel_name = channel_info['name']
110 availability_data_source = AvailabilityDataSource(
111 CHROME_VERSION_DATA_SOURCE,
112 channel_info['version'],
113 AVAILABILITY_DATA_SOURCE_MEMCACHE)
114
115 branch_memcache = InMemoryObjectStore(branch_number)
116 file_system = _CreateMemcacheFileSystem(branch_number, branch_memcache)
117 cache_factory = CompiledFileSystem.Factory(file_system, branch_memcache)
118 api_list_data_source_factory = APIListDataSource.Factory(
119 cache_factory,
120 file_system,
121 API_PATH,
122 PUBLIC_TEMPLATE_PATH)
123 api_data_source_factory = APIDataSource.Factory(cache_factory,
124 API_PATH,
125 availability_data_source)
126 # Give the ReferenceResolver a memcache, to speed up the lookup of
127 # duplicate $refs.
128 ref_resolver_factory = ReferenceResolver.Factory(
129 api_data_source_factory,
130 api_list_data_source_factory,
131 branch_memcache)
132 api_data_source_factory.SetReferenceResolverFactory(ref_resolver_factory)
133 samples_data_source_factory = SamplesDataSource.Factory(
134 channel_name,
135 file_system,
136 GITHUB_FILE_SYSTEM,
137 cache_factory,
138 GITHUB_COMPILED_FILE_SYSTEM,
139 ref_resolver_factory,
140 EXAMPLES_PATH)
141 api_data_source_factory.SetSamplesDataSourceFactory(
142 samples_data_source_factory)
143
144 if channel_info is not None:
145 intro_data_source_factory = IntroDataSource.Factory(
146 cache_factory,
147 ref_resolver_factory,
148 [INTRO_PATH, ARTICLE_PATH])
149 sidenav_data_source_factory = SidenavDataSource.Factory(cache_factory,
150 JSON_PATH)
151 template_data_source_factory = TemplateDataSource.Factory(
152 channel_name,
153 api_data_source_factory,
154 api_list_data_source_factory,
155 intro_data_source_factory,
156 samples_data_source_factory,
157 KNOWN_ISSUES_DATA_SOURCE,
158 sidenav_data_source_factory,
159 cache_factory,
160 ref_resolver_factory,
161 PUBLIC_TEMPLATE_PATH,
162 PRIVATE_TEMPLATE_PATH,
163 BRANCH_UTILITY.GetChannelInfoForAllChannels())
164 example_zipper = ExampleZipper(file_system,
165 cache_factory,
166 DOCS_PATH)
167 instance = ServerInstance(template_data_source_factory,
168 example_zipper,
169 cache_factory)
170 return instance
171 return api_data_source_factory.Create(None)
172
173 _default_branch = BRANCH_UTILITY.GetChannelInfoForChannelName(
174 _DEFAULT_CHANNEL)['branch']
88 APPS_MEMCACHE = InMemoryObjectStore(_default_branch) 175 APPS_MEMCACHE = InMemoryObjectStore(_default_branch)
89 APPS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, APPS_MEMCACHE) 176 APPS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, APPS_MEMCACHE)
90 APPS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory( 177 APPS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory(
91 APPS_FILE_SYSTEM, 178 APPS_FILE_SYSTEM,
92 APPS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.APPS_FS) 179 APPS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.APPS_FS)
93 180
94 EXTENSIONS_MEMCACHE = InMemoryObjectStore(_default_branch) 181 EXTENSIONS_MEMCACHE = InMemoryObjectStore(_default_branch)
95 EXTENSIONS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, 182 EXTENSIONS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch,
96 EXTENSIONS_MEMCACHE) 183 EXTENSIONS_MEMCACHE)
97 EXTENSIONS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory( 184 EXTENSIONS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory(
98 EXTENSIONS_FILE_SYSTEM, 185 EXTENSIONS_FILE_SYSTEM,
99 EXTENSIONS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.EXTENSIONS_FS) 186 EXTENSIONS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.EXTENSIONS_FS)
100 187
101 KNOWN_ISSUES_DATA_SOURCE = KnownIssuesDataSource( 188 KNOWN_ISSUES_DATA_SOURCE = KnownIssuesDataSource(
102 InMemoryObjectStore('KnownIssues'), 189 InMemoryObjectStore('KnownIssues'),
103 AppEngineUrlFetcher(None)) 190 AppEngineUrlFetcher(None))
104 191
192 CHROME_VERSION_DATA_SOURCE_MEMCACHE = InMemoryObjectStore(
193 'chrome_version_data_source')
194 CHROME_VERSION_DATA_SOURCE = ChromeVersionDataSource(
195 url_constants.OMAHA_BETA_HISTORY,
196 AppEngineUrlFetcher(None),
197 CHROME_VERSION_DATA_SOURCE_MEMCACHE,
cduvall 2013/03/28 22:18:35 Just construct this inline
epeterson 2013/03/28 23:50:36 Done. And why didn't everything just have a 4-spac
198 _CreateAPIDataSourceForBranch)
199
105 def _MakeInstanceKey(branch, number): 200 def _MakeInstanceKey(branch, number):
106 return '%s/%s' % (branch, number) 201 return '%s/%s' % (branch, number)
107 202
108 def _GetInstanceForBranch(channel_name, local_path): 203 def _GetInstanceForBranch(channel_name, local_path):
109 branch = BRANCH_UTILITY.GetBranchNumberForChannelName(channel_name) 204 channel_info = BRANCH_UTILITY.GetChannelInfoForChannelName(
205 channel_name)
206 branch = channel_info['branch']
110 207
111 # The key for the server is a tuple of |channel_name| with |branch|, since 208 # The key for the server is a tuple of |channel_name| with |branch|, since
112 # sometimes stable and beta point to the same branch. 209 # sometimes stable and beta point to the same branch.
113 instance_key = _MakeInstanceKey(channel_name, branch) 210 instance_key = _MakeInstanceKey(channel_name, branch)
114 instance = SERVER_INSTANCES.get(instance_key, None) 211 instance = SERVER_INSTANCES.get(instance_key, None)
115 if instance is not None: 212 if instance is not None:
116 return instance 213 return instance
117 214
118 branch_memcache = InMemoryObjectStore(branch) 215 instance = _CreateInstanceForBranch(branch, channel_info)
119 file_system = _CreateMemcacheFileSystem(branch, branch_memcache) 216 SERVER_INSTANCES[instance_key] = instance
120 cache_factory = CompiledFileSystem.Factory(file_system, branch_memcache)
121 api_list_data_source_factory = APIListDataSource.Factory(cache_factory,
122 file_system,
123 API_PATH,
124 PUBLIC_TEMPLATE_PATH)
125 api_data_source_factory = APIDataSource.Factory(
126 cache_factory,
127 API_PATH)
128 217
129 # Give the ReferenceResolver a memcache, to speed up the lookup of
130 # duplicate $refs.
131 ref_resolver_factory = ReferenceResolver.Factory(
132 api_data_source_factory,
133 api_list_data_source_factory,
134 branch_memcache)
135 api_data_source_factory.SetReferenceResolverFactory(ref_resolver_factory)
136 samples_data_source_factory = SamplesDataSource.Factory(
137 channel_name,
138 file_system,
139 GITHUB_FILE_SYSTEM,
140 cache_factory,
141 GITHUB_COMPILED_FILE_SYSTEM,
142 ref_resolver_factory,
143 EXAMPLES_PATH)
144 api_data_source_factory.SetSamplesDataSourceFactory(
145 samples_data_source_factory)
146 intro_data_source_factory = IntroDataSource.Factory(
147 cache_factory,
148 ref_resolver_factory,
149 [INTRO_PATH, ARTICLE_PATH])
150 sidenav_data_source_factory = SidenavDataSource.Factory(cache_factory,
151 JSON_PATH)
152 template_data_source_factory = TemplateDataSource.Factory(
153 channel_name,
154 api_data_source_factory,
155 api_list_data_source_factory,
156 intro_data_source_factory,
157 samples_data_source_factory,
158 KNOWN_ISSUES_DATA_SOURCE,
159 sidenav_data_source_factory,
160 cache_factory,
161 ref_resolver_factory,
162 PUBLIC_TEMPLATE_PATH,
163 PRIVATE_TEMPLATE_PATH)
164 example_zipper = ExampleZipper(file_system,
165 cache_factory,
166 DOCS_PATH)
167
168 instance = ServerInstance(template_data_source_factory,
169 example_zipper,
170 cache_factory)
171 SERVER_INSTANCES[instance_key] = instance
172 return instance 218 return instance
173 219
174 def _CleanBranches(): 220 def _CleanBranches():
175 keys = [_MakeInstanceKey(branch, number) 221 keys = [_MakeInstanceKey(branch, number)
176 for branch, number in BRANCH_UTILITY.GetAllBranchNumbers()] 222 for branch, number in BRANCH_UTILITY.GetAllBranchNumbers()]
177 for key in SERVER_INSTANCES.keys(): 223 for key in SERVER_INSTANCES.keys():
178 if key not in keys: 224 if key not in keys:
179 SERVER_INSTANCES.pop(key) 225 SERVER_INSTANCES.pop(key)
180 226
181 class _MockResponse(object): 227 class _MockResponse(object):
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 265
220 _CleanBranches() 266 _CleanBranches()
221 267
222 # Yes, do this after it's passed to RedirectBadPaths. That needs to know 268 # Yes, do this after it's passed to RedirectBadPaths. That needs to know
223 # whether or not a branch was specified. 269 # whether or not a branch was specified.
224 if channel_name is None: 270 if channel_name is None:
225 channel_name = _DEFAULT_CHANNEL 271 channel_name = _DEFAULT_CHANNEL
226 _GetInstanceForBranch(channel_name, self._local_path).Get(real_path, 272 _GetInstanceForBranch(channel_name, self._local_path).Get(real_path,
227 self.request, 273 self.request,
228 self.response) 274 self.response)
229
230 def _Render(self, files, channel): 275 def _Render(self, files, channel):
231 original_response = self.response 276 original_response = self.response
232 for f in files: 277 for f in files:
233 if f.endswith('404.html'): 278 if f.endswith('404.html'):
234 continue 279 continue
235 path = channel + f.split(PUBLIC_TEMPLATE_PATH)[-1] 280 path = channel + f.split(PUBLIC_TEMPLATE_PATH)[-1]
236 self.request = _MockRequest(path) 281 self.request = _MockRequest(path)
237 self.response = _MockResponse() 282 self.response = _MockResponse()
238 try: 283 try:
239 self._HandleGet(path) 284 self._HandleGet(path)
(...skipping 19 matching lines...) Expand all
259 # We could list all files in PUBLIC_TEMPLATE_PATH then render them. However, 304 # We could list all files in PUBLIC_TEMPLATE_PATH then render them. However,
260 # this would be inefficient in the common case where files haven't changed 305 # this would be inefficient in the common case where files haven't changed
261 # since the last cron. 306 # since the last cron.
262 # 307 #
263 # Instead, let the CompiledFileSystem give us clues when to re-render: we 308 # Instead, let the CompiledFileSystem give us clues when to re-render: we
264 # use the CFS to check whether the templates, examples, or API folders have 309 # use the CFS to check whether the templates, examples, or API folders have
265 # been changed. If there has been a change, the compilation function will 310 # been changed. If there has been a change, the compilation function will
266 # be called. The same is then done separately with the apps samples page, 311 # be called. The same is then done separately with the apps samples page,
267 # since it pulls its data from Github. 312 # since it pulls its data from Github.
268 channel = path.split('/')[-1] 313 channel = path.split('/')[-1]
269 branch = BRANCH_UTILITY.GetBranchNumberForChannelName(channel) 314 branch = BRANCH_UTILITY.GetChannelInfoForChannelName(channel)['branch']
270 logging.info('Running cron job for %s.' % branch) 315 logging.info('Running cron job for %s.' % branch)
271 branch_memcache = InMemoryObjectStore(branch) 316 branch_memcache = InMemoryObjectStore(branch)
272 file_system = _CreateMemcacheFileSystem(branch, branch_memcache) 317 file_system = _CreateMemcacheFileSystem(branch, branch_memcache)
273 factory = CompiledFileSystem.Factory(file_system, branch_memcache) 318 factory = CompiledFileSystem.Factory(file_system, branch_memcache)
274 319
275 needs_render = self._ValueHolder(False) 320 needs_render = self._ValueHolder(False)
276 invalidation_cache = factory.Create(lambda _, __: needs_render.Set(True), 321 invalidation_cache = factory.Create(lambda _, __: needs_render.Set(True),
277 compiled_fs.CRON_INVALIDATION, 322 compiled_fs.CRON_INVALIDATION,
278 version=_VERSION) 323 version=_VERSION)
279 for path in [TEMPLATE_PATH, EXAMPLES_PATH, API_PATH]: 324 for path in [TEMPLATE_PATH, EXAMPLES_PATH, API_PATH]:
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 412
368 # Redirect paths like "directory" to "directory/". This is so relative 413 # Redirect paths like "directory" to "directory/". This is so relative
369 # file paths will know to treat this as a directory. 414 # file paths will know to treat this as a directory.
370 if os.path.splitext(path)[1] == '' and path[-1] != '/': 415 if os.path.splitext(path)[1] == '' and path[-1] != '/':
371 self.redirect(path + '/') 416 self.redirect(path + '/')
372 return 417 return
373 418
374 path = path.strip('/') 419 path = path.strip('/')
375 if not self._RedirectFromCodeDotGoogleDotCom(path): 420 if not self._RedirectFromCodeDotGoogleDotCom(path):
376 self._HandleGet(path) 421 self._HandleGet(path)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698