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

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

Issue 462103003: Docserver: Implement ContentProvider.GetVersion. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: futurize Created 6 years, 4 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 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 logging 5 import logging
6 import mimetypes 6 import mimetypes
7 import posixpath 7 import posixpath
8 import traceback 8 import traceback
9 9
10 from compiled_file_system import SingleFile 10 from compiled_file_system import SingleFile
11 from directory_zipper import DirectoryZipper 11 from directory_zipper import DirectoryZipper
12 from docs_server_utils import ToUnicode 12 from docs_server_utils import ToUnicode
13 from file_system import FileNotFoundError 13 from file_system import FileNotFoundError
14 from future import Future 14 from future import All, Future
15 from path_canonicalizer import PathCanonicalizer 15 from path_canonicalizer import PathCanonicalizer
16 from path_util import AssertIsValid, IsDirectory, Join, ToDirectory 16 from path_util import AssertIsValid, IsDirectory, Join, ToDirectory
17 from special_paths import SITE_VERIFICATION_FILE 17 from special_paths import SITE_VERIFICATION_FILE
18 from third_party.handlebar import Handlebar 18 from third_party.handlebar import Handlebar
19 from third_party.markdown import markdown 19 from third_party.markdown import markdown
20 20
21 21
22 _MIMETYPE_OVERRIDES = { 22 _MIMETYPE_OVERRIDES = {
23 # SVG is not supported by mimetypes.guess_type on AppEngine. 23 # SVG is not supported by mimetypes.guess_type on AppEngine.
24 '.svg': 'image/svg+xml', 24 '.svg': 'image/svg+xml',
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 ''' 122 '''
123 AssertIsValid(path) 123 AssertIsValid(path)
124 base, ext = posixpath.splitext(path) 124 base, ext = posixpath.splitext(path)
125 if self._directory_zipper and ext == '.zip': 125 if self._directory_zipper and ext == '.zip':
126 # The canonical location of zip files is the canonical location of the 126 # The canonical location of zip files is the canonical location of the
127 # directory to zip + '.zip'. 127 # directory to zip + '.zip'.
128 return self._path_canonicalizer.Canonicalize(base + '/').rstrip('/') + ext 128 return self._path_canonicalizer.Canonicalize(base + '/').rstrip('/') + ext
129 return self._path_canonicalizer.Canonicalize(path) 129 return self._path_canonicalizer.Canonicalize(path)
130 130
131 def GetContentAndType(self, path): 131 def GetContentAndType(self, path):
132 '''Returns the ContentAndType of the file at |path|. 132 '''Returns a Future to the ContentAndType of the file at |path|.
133 ''' 133 '''
134 AssertIsValid(path) 134 AssertIsValid(path)
135 base, ext = posixpath.splitext(path) 135 base, ext = posixpath.splitext(path)
136 if self._directory_zipper and ext == '.zip':
137 return (self._directory_zipper.Zip(ToDirectory(base))
138 .Then(lambda zipped: ContentAndType(zipped,
139 'application/zip',
140 None)))
141 return self._FindFileForPath(path).Then(self._content_cache.GetFromFile)
136 142
137 # Check for a zip file first, if zip is enabled. 143 def GetVersion(self, path):
144 '''Returns a Future to the version of the file at |path|.
145 '''
146 AssertIsValid(path)
147 base, ext = posixpath.splitext(path)
138 if self._directory_zipper and ext == '.zip': 148 if self._directory_zipper and ext == '.zip':
139 zip_future = self._directory_zipper.Zip(ToDirectory(base)) 149 stat_future = self.file_system.StatAsync(ToDirectory(base))
140 return Future(callback= 150 else:
141 lambda: ContentAndType(zip_future.Get(), 'application/zip', None)) 151 stat_future = self._FindFileForPath(path).Then(self.file_system.StatAsync)
152 return stat_future.Then(lambda stat: stat.version)
142 153
143 # If there is no file extension, look for a file with one of the default 154 def _FindFileForPath(self, path):
144 # extensions. If one cannot be found, check if the path is a directory. 155 '''Finds the real file backing |path|. This may require looking for the
145 # If it is, then check for an index file with one of the default 156 correct file extension, or looking for an 'index' file if it's a directory.
146 # extensions. 157 Returns None if no path is found.
147 if not ext: 158 '''
148 new_path = self._AddExt(path) 159 AssertIsValid(path)
149 # Add a trailing / to check if it is a directory and not a file with 160 _, ext = posixpath.splitext(path)
150 # no extension.
151 if new_path is None and self.file_system.Exists(ToDirectory(path)).Get():
152 new_path = self._AddExt(Join(path, 'index'))
153 # If an index file wasn't found in this directly then we're never going
154 # to find a file.
155 if new_path is None:
156 return FileNotFoundError.RaiseInFuture('"%s" is a directory' % path)
157 if new_path is not None:
158 path = new_path
159 161
160 return self._content_cache.GetFromFile(path) 162 if ext:
163 # There was already an extension, trust that it's a path. Elsewhere
164 # up the stack this will be caught if it's not.
165 return Future(value=path)
161 166
162 def _AddExt(self, path): 167 def find_file_with_name(name):
163 '''Tries to append each of the default file extensions to path and returns 168 '''Tries to find a file in the file system called |name| with one of the
164 the first one that is an existing file. 169 default extensions of this content provider.
165 ''' 170 If none is found, returns None.
166 for default_ext in self._default_extensions: 171 '''
167 if self.file_system.Exists(path + default_ext).Get(): 172 paths = [name + ext for ext in self._default_extensions]
168 return path + default_ext 173 def get_first_path_which_exists(existence):
Yoyo Zhou 2014/08/13 18:30:50 Seems like this wants to be a Race. But maybe it s
not at google - send to devlin 2014/08/13 19:38:22 Yeah I wish it could be a Race, but Race returns t
Yoyo Zhou 2014/08/13 20:34:15 Well, you should be able to do this like Race((se
169 return None 174 for exists, path in zip(existence, paths):
175 if exists:
176 return path
177 return None
178 return (All(self.file_system.Exists(path) for path in paths)
179 .Then(get_first_path_which_exists))
180
181 def find_index_file():
182 '''Tries to find an index file in |path|, if |path| is a directory.
183 If not, or if there is no index file, returns None.
184 '''
185 def get_index_if_directory_exists(directory_exists):
186 if not directory_exists:
187 return None
188 return find_file_with_name(Join(path, 'index'))
189 return (self.file_system.Exists(ToDirectory(path))
190 .Then(get_index_if_directory_exists))
191
192 # Try to find a file with the right name. If not, and it's a directory,
193 # look for an index file in that directory. If nothing at all is found,
194 # return the original |path| - its nonexistence will be caught up the stack.
195 return (find_file_with_name(path)
196 .Then(lambda found: found or find_index_file())
197 .Then(lambda found: found or path))
170 198
171 def Cron(self): 199 def Cron(self):
172 futures = [('<path_canonicalizer>', # semi-arbitrary string since there is 200 futures = [self._path_canonicalizer.Cron()]
173 # no path associated with this Future.
174 self._path_canonicalizer.Cron())]
175 for root, _, files in self.file_system.Walk(''): 201 for root, _, files in self.file_system.Walk(''):
176 for f in files: 202 for f in files:
177 futures.append((Join(root, f), 203 futures.append(self.GetContentAndType(Join(root, f)))
178 self.GetContentAndType(Join(root, f))))
179 # Also cache the extension-less version of the file if needed. 204 # Also cache the extension-less version of the file if needed.
180 base, ext = posixpath.splitext(f) 205 base, ext = posixpath.splitext(f)
181 if f != SITE_VERIFICATION_FILE and ext in self._default_extensions: 206 if f != SITE_VERIFICATION_FILE and ext in self._default_extensions:
182 futures.append((Join(root, base), 207 futures.append(self.GetContentAndType(Join(root, base)))
183 self.GetContentAndType(Join(root, base))))
184 # TODO(kalman): Cache .zip files for each directory (if supported). 208 # TODO(kalman): Cache .zip files for each directory (if supported).
185 def resolve(): 209 return All(futures, except_pass=Exception, except_pass_log=True)
186 for label, future in futures:
187 try: future.Get()
188 except: logging.error('%s: %s' % (label, traceback.format_exc()))
189 return Future(callback=resolve)
190 210
191 def __repr__(self): 211 def __repr__(self):
192 return 'ContentProvider of <%s>' % repr(self.file_system) 212 return 'ContentProvider of <%s>' % repr(self.file_system)
OLDNEW
« no previous file with comments | « chrome/common/extensions/docs/server2/app.yaml ('k') | chrome/common/extensions/docs/server2/content_provider_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698