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

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: First round of 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 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
54
49 GITHUB_MEMCACHE = InMemoryObjectStore('github') 55 GITHUB_MEMCACHE = InMemoryObjectStore('github')
50 GITHUB_FILE_SYSTEM = GithubFileSystem( 56 GITHUB_FILE_SYSTEM = GithubFileSystem(
51 AppEngineUrlFetcher(url_constants.GITHUB_URL), 57 AppEngineUrlFetcher(url_constants.GITHUB_URL),
52 GITHUB_MEMCACHE, 58 GITHUB_MEMCACHE,
53 AppEngineBlobstore()) 59 AppEngineBlobstore())
54 GITHUB_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory(GITHUB_FILE_SYSTEM, 60 GITHUB_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory(GITHUB_FILE_SYSTEM,
55 GITHUB_MEMCACHE) 61 GITHUB_MEMCACHE)
56 62
57 EXTENSIONS_PATH = 'chrome/common/extensions' 63 EXTENSIONS_PATH = 'chrome/common/extensions'
58 DOCS_PATH = 'docs' 64 DOCS_PATH = 'docs'
(...skipping 18 matching lines...) Expand all
77 return [UnixName(os.path.splitext(f.split('/')[-1])[0]) for f in files] 83 return [UnixName(os.path.splitext(f.split('/')[-1])[0]) for f in files]
78 84
79 def _CreateMemcacheFileSystem(branch, branch_memcache): 85 def _CreateMemcacheFileSystem(branch, branch_memcache):
80 svn_url = _GetURLFromBranch(branch) + '/' + EXTENSIONS_PATH 86 svn_url = _GetURLFromBranch(branch) + '/' + EXTENSIONS_PATH
81 stat_fetcher = AppEngineUrlFetcher( 87 stat_fetcher = AppEngineUrlFetcher(
82 svn_url.replace(url_constants.SVN_URL, url_constants.VIEWVC_URL)) 88 svn_url.replace(url_constants.SVN_URL, url_constants.VIEWVC_URL))
83 fetcher = AppEngineUrlFetcher(svn_url) 89 fetcher = AppEngineUrlFetcher(svn_url)
84 return MemcacheFileSystem(SubversionFileSystem(fetcher, stat_fetcher), 90 return MemcacheFileSystem(SubversionFileSystem(fetcher, stat_fetcher),
85 branch_memcache) 91 branch_memcache)
86 92
87 _default_branch = BRANCH_UTILITY.GetBranchNumberForChannelName(_DEFAULT_CHANNEL) 93 def _CreateMemcacheForBranch(branch_number):
epeterson 2013/03/25 19:48:02 This is now a global method, which is passed to th
cduvall 2013/03/25 22:59:43 Which objects does it depend on? Can you just pass
94 """Passed to the global instance of chromeVersionDataSource. Allows for
95 the creation of api_data_sources linked to |branch_number|, which is the
96 maximum branch number from a given version of chrome.
97 """
98 branch_memcache = InMemoryObjectStore(branch_number)
99 file_system = _CreateMemcacheFileSystem(branch_number, branch_memcache)
100 cache_factory = CompiledFileSystem.Factory(file_system, branch_memcache)
101 api_list_data_source_factory = APIListDataSource.Factory(
102 cache_factory,
103 file_system,
104 API_PATH,
105 PUBLIC_TEMPLATE_PATH)
106 api_data_source_factory = APIDataSource.Factory(cache_factory, API_PATH)
107 ref_resolver_factory = ReferenceResolver.Factory(
108 api_data_source_factory,
109 api_list_data_source_factory,
110 branch_memcache)
111 api_data_source_factory.SetReferenceResolverFactory(ref_resolver_factory)
112 samples_data_source_factory = SamplesDataSource.Factory(
113 #channel_name,
114 'trunk',
epeterson 2013/03/25 19:48:02 This is really the only part that prevents this me
cduvall 2013/03/25 22:59:43 Can you just pass the channel name in as a functio
115 file_system,
116 GITHUB_FILE_SYSTEM,
117 cache_factory,
118 GITHUB_COMPILED_FILE_SYSTEM,
119 ref_resolver_factory,
120 EXAMPLES_PATH)
121 api_data_source_factory.SetSamplesDataSourceFactory(
122 samples_data_source_factory)
123 return api_data_source_factory.Create(None)
124
125 _default_branch = BRANCH_UTILITY.GetChannelInfoForChannelName(
126 _DEFAULT_CHANNEL)['branch']
88 APPS_MEMCACHE = InMemoryObjectStore(_default_branch) 127 APPS_MEMCACHE = InMemoryObjectStore(_default_branch)
89 APPS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, APPS_MEMCACHE) 128 APPS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, APPS_MEMCACHE)
90 APPS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory( 129 APPS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory(
91 APPS_FILE_SYSTEM, 130 APPS_FILE_SYSTEM,
92 APPS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.APPS_FS) 131 APPS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.APPS_FS)
93 132
94 EXTENSIONS_MEMCACHE = InMemoryObjectStore(_default_branch) 133 EXTENSIONS_MEMCACHE = InMemoryObjectStore(_default_branch)
95 EXTENSIONS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch, 134 EXTENSIONS_FILE_SYSTEM = _CreateMemcacheFileSystem(_default_branch,
96 EXTENSIONS_MEMCACHE) 135 EXTENSIONS_MEMCACHE)
97 EXTENSIONS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory( 136 EXTENSIONS_COMPILED_FILE_SYSTEM = CompiledFileSystem.Factory(
98 EXTENSIONS_FILE_SYSTEM, 137 EXTENSIONS_FILE_SYSTEM,
99 EXTENSIONS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.EXTENSIONS_FS) 138 EXTENSIONS_MEMCACHE).Create(_SplitFilenameUnix, compiled_fs.EXTENSIONS_FS)
100 139
101 KNOWN_ISSUES_DATA_SOURCE = KnownIssuesDataSource( 140 KNOWN_ISSUES_DATA_SOURCE = KnownIssuesDataSource(
102 InMemoryObjectStore('KnownIssues'), 141 InMemoryObjectStore('KnownIssues'),
103 AppEngineUrlFetcher(None)) 142 AppEngineUrlFetcher(None))
104 143
144 CHROME_VERSION_DATA_SOURCE_MEMCACHE = InMemoryObjectStore(
145 'chrome_version_data_source')
146 CHROME_VERSION_DATA_SOURCE = ChromeVersionDataSource(
147 url_constants.OMAHA_BETA_HISTORY,
148 AppEngineUrlFetcher(None),
149 CHROME_VERSION_DATA_SOURCE_MEMCACHE,
150 _CreateMemcacheForBranch)
151
105 def _MakeInstanceKey(branch, number): 152 def _MakeInstanceKey(branch, number):
106 return '%s/%s' % (branch, number) 153 return '%s/%s' % (branch, number)
107 154
108 def _GetInstanceForBranch(channel_name, local_path): 155 def _GetInstanceForBranch(channel_name, local_path):
109 branch = BRANCH_UTILITY.GetBranchNumberForChannelName(channel_name) 156 channel_info = BRANCH_UTILITY.GetChannelInfoForChannelName(
157 channel_name)
158 branch = channel_info['branch']
159 version = channel_info['version']
110 160
111 # The key for the server is a tuple of |channel_name| with |branch|, since 161 # The key for the server is a tuple of |channel_name| with |branch|, since
112 # sometimes stable and beta point to the same branch. 162 # sometimes stable and beta point to the same branch.
113 instance_key = _MakeInstanceKey(channel_name, branch) 163 instance_key = _MakeInstanceKey(channel_name, branch)
114 instance = SERVER_INSTANCES.get(instance_key, None) 164 instance = SERVER_INSTANCES.get(instance_key, None)
115 if instance is not None: 165 if instance is not None:
116 return instance 166 return instance
117
118 branch_memcache = InMemoryObjectStore(branch) 167 branch_memcache = InMemoryObjectStore(branch)
119 file_system = _CreateMemcacheFileSystem(branch, branch_memcache) 168 file_system = _CreateMemcacheFileSystem(branch, branch_memcache)
120 cache_factory = CompiledFileSystem.Factory(file_system, branch_memcache) 169 cache_factory = CompiledFileSystem.Factory(file_system, branch_memcache)
121 api_list_data_source_factory = APIListDataSource.Factory(cache_factory, 170 api_list_data_source_factory = APIListDataSource.Factory(cache_factory,
122 file_system, 171 file_system,
123 API_PATH, 172 API_PATH,
124 PUBLIC_TEMPLATE_PATH) 173 PUBLIC_TEMPLATE_PATH)
174 availability_data_source = AvailabilityDataSource(
175 CHROME_VERSION_DATA_SOURCE,
176 version,
177 AVAILABILITY_DATA_SOURCE_MEMCACHE)
125 api_data_source_factory = APIDataSource.Factory( 178 api_data_source_factory = APIDataSource.Factory(
126 cache_factory, 179 cache_factory,
127 API_PATH) 180 API_PATH,
181 availability_data_source)
128 182
129 # Give the ReferenceResolver a memcache, to speed up the lookup of 183 # Give the ReferenceResolver a memcache, to speed up the lookup of
130 # duplicate $refs. 184 # duplicate $refs.
131 ref_resolver_factory = ReferenceResolver.Factory( 185 ref_resolver_factory = ReferenceResolver.Factory(
132 api_data_source_factory, 186 api_data_source_factory,
133 api_list_data_source_factory, 187 api_list_data_source_factory,
134 branch_memcache) 188 branch_memcache)
135 api_data_source_factory.SetReferenceResolverFactory(ref_resolver_factory) 189 api_data_source_factory.SetReferenceResolverFactory(ref_resolver_factory)
136 samples_data_source_factory = SamplesDataSource.Factory( 190 samples_data_source_factory = SamplesDataSource.Factory(
137 channel_name, 191 channel_name,
138 file_system, 192 file_system,
139 GITHUB_FILE_SYSTEM, 193 GITHUB_FILE_SYSTEM,
140 cache_factory, 194 cache_factory,
141 GITHUB_COMPILED_FILE_SYSTEM, 195 GITHUB_COMPILED_FILE_SYSTEM,
142 ref_resolver_factory, 196 ref_resolver_factory,
143 EXAMPLES_PATH) 197 EXAMPLES_PATH)
144 api_data_source_factory.SetSamplesDataSourceFactory( 198 api_data_source_factory.SetSamplesDataSourceFactory(
145 samples_data_source_factory) 199 samples_data_source_factory)
146 intro_data_source_factory = IntroDataSource.Factory( 200 intro_data_source_factory = IntroDataSource.Factory(
147 cache_factory, 201 cache_factory,
148 ref_resolver_factory, 202 ref_resolver_factory,
149 [INTRO_PATH, ARTICLE_PATH]) 203 [INTRO_PATH, ARTICLE_PATH])
150 sidenav_data_source_factory = SidenavDataSource.Factory(cache_factory, 204 sidenav_data_source_factory = SidenavDataSource.Factory(cache_factory,
151 JSON_PATH) 205 JSON_PATH)
cduvall 2013/03/25 22:59:43 revert
epeterson 2013/03/27 22:36:09 Done, in the new global method.
152 template_data_source_factory = TemplateDataSource.Factory( 206 template_data_source_factory = TemplateDataSource.Factory(
153 channel_name, 207 channel_name,
154 api_data_source_factory, 208 api_data_source_factory,
155 api_list_data_source_factory, 209 api_list_data_source_factory,
156 intro_data_source_factory, 210 intro_data_source_factory,
157 samples_data_source_factory, 211 samples_data_source_factory,
158 KNOWN_ISSUES_DATA_SOURCE, 212 KNOWN_ISSUES_DATA_SOURCE,
159 sidenav_data_source_factory, 213 sidenav_data_source_factory,
160 cache_factory, 214 cache_factory,
161 ref_resolver_factory, 215 ref_resolver_factory,
162 PUBLIC_TEMPLATE_PATH, 216 PUBLIC_TEMPLATE_PATH,
163 PRIVATE_TEMPLATE_PATH) 217 PRIVATE_TEMPLATE_PATH,
218 BRANCH_UTILITY.GetChannelInfoForAllChannels())
164 example_zipper = ExampleZipper(file_system, 219 example_zipper = ExampleZipper(file_system,
165 cache_factory, 220 cache_factory,
166 DOCS_PATH) 221 DOCS_PATH)
167
168 instance = ServerInstance(template_data_source_factory, 222 instance = ServerInstance(template_data_source_factory,
169 example_zipper, 223 example_zipper,
170 cache_factory) 224 cache_factory)
171 SERVER_INSTANCES[instance_key] = instance 225 SERVER_INSTANCES[instance_key] = instance
172 return instance 226 return instance
173 227
174 def _CleanBranches(): 228 def _CleanBranches():
175 keys = [_MakeInstanceKey(branch, number) 229 keys = [_MakeInstanceKey(branch, number)
176 for branch, number in BRANCH_UTILITY.GetAllBranchNumbers()] 230 for branch, number in BRANCH_UTILITY.GetAllBranchNumbers()]
177 for key in SERVER_INSTANCES.keys(): 231 for key in SERVER_INSTANCES.keys():
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 273
220 _CleanBranches() 274 _CleanBranches()
221 275
222 # Yes, do this after it's passed to RedirectBadPaths. That needs to know 276 # Yes, do this after it's passed to RedirectBadPaths. That needs to know
223 # whether or not a branch was specified. 277 # whether or not a branch was specified.
224 if channel_name is None: 278 if channel_name is None:
225 channel_name = _DEFAULT_CHANNEL 279 channel_name = _DEFAULT_CHANNEL
226 _GetInstanceForBranch(channel_name, self._local_path).Get(real_path, 280 _GetInstanceForBranch(channel_name, self._local_path).Get(real_path,
227 self.request, 281 self.request,
228 self.response) 282 self.response)
229
230 def _Render(self, files, channel): 283 def _Render(self, files, channel):
231 original_response = self.response 284 original_response = self.response
232 for f in files: 285 for f in files:
233 if f.endswith('404.html'): 286 if f.endswith('404.html'):
234 continue 287 continue
235 path = channel + f.split(PUBLIC_TEMPLATE_PATH)[-1] 288 path = channel + f.split(PUBLIC_TEMPLATE_PATH)[-1]
236 self.request = _MockRequest(path) 289 self.request = _MockRequest(path)
237 self.response = _MockResponse() 290 self.response = _MockResponse()
238 try: 291 try:
239 self._HandleGet(path) 292 self._HandleGet(path)
(...skipping 19 matching lines...) Expand all
259 # We could list all files in PUBLIC_TEMPLATE_PATH then render them. However, 312 # 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 313 # this would be inefficient in the common case where files haven't changed
261 # since the last cron. 314 # since the last cron.
262 # 315 #
263 # Instead, let the CompiledFileSystem give us clues when to re-render: we 316 # 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 317 # 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 318 # 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, 319 # be called. The same is then done separately with the apps samples page,
267 # since it pulls its data from Github. 320 # since it pulls its data from Github.
268 channel = path.split('/')[-1] 321 channel = path.split('/')[-1]
269 branch = BRANCH_UTILITY.GetBranchNumberForChannelName(channel) 322 branch = BRANCH_UTILITY.GetChannelInfoForChannelName(channel)['branch']
270 logging.info('Running cron job for %s.' % branch) 323 logging.info('Running cron job for %s.' % branch)
271 branch_memcache = InMemoryObjectStore(branch) 324 branch_memcache = InMemoryObjectStore(branch)
272 file_system = _CreateMemcacheFileSystem(branch, branch_memcache) 325 file_system = _CreateMemcacheFileSystem(branch, branch_memcache)
273 factory = CompiledFileSystem.Factory(file_system, branch_memcache) 326 factory = CompiledFileSystem.Factory(file_system, branch_memcache)
274 327
275 needs_render = self._ValueHolder(False) 328 needs_render = self._ValueHolder(False)
276 invalidation_cache = factory.Create(lambda _, __: needs_render.Set(True), 329 invalidation_cache = factory.Create(lambda _, __: needs_render.Set(True),
277 compiled_fs.CRON_INVALIDATION, 330 compiled_fs.CRON_INVALIDATION,
278 version=_VERSION) 331 version=_VERSION)
279 for path in [TEMPLATE_PATH, EXAMPLES_PATH, API_PATH]: 332 for path in [TEMPLATE_PATH, EXAMPLES_PATH, API_PATH]:
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 420
368 # Redirect paths like "directory" to "directory/". This is so relative 421 # Redirect paths like "directory" to "directory/". This is so relative
369 # file paths will know to treat this as a directory. 422 # file paths will know to treat this as a directory.
370 if os.path.splitext(path)[1] == '' and path[-1] != '/': 423 if os.path.splitext(path)[1] == '' and path[-1] != '/':
371 self.redirect(path + '/') 424 self.redirect(path + '/')
372 return 425 return
373 426
374 path = path.strip('/') 427 path = path.strip('/')
375 if not self._RedirectFromCodeDotGoogleDotCom(path): 428 if not self._RedirectFromCodeDotGoogleDotCom(path):
376 self._HandleGet(path) 429 self._HandleGet(path)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698