OLD | NEW |
---|---|
1 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 # for details. All rights reserved. Use of this source code is governed by a | 2 # for details. All rights reserved. Use of this source code is governed by a |
3 # BSD-style license that can be found in the LICENSE file. | 3 # BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 """Utility functions for dealing with Google Cloud Storage.""" | 5 """Utility functions for dealing with Google Cloud Storage.""" |
6 | 6 |
7 from cStringIO import StringIO | 7 from cStringIO import StringIO |
8 from base64 import b64encode | 8 from base64 import b64encode |
9 from urlparse import urlparse, parse_qs | 9 from urlparse import urlparse, parse_qs |
10 from xml.etree import ElementTree | 10 from xml.etree import ElementTree |
11 import cherrypy | 11 import cherrypy |
12 import handlers | 12 import handlers |
13 import json | 13 import json |
14 import routes | 14 import routes |
15 import urllib | 15 import urllib |
16 import time | 16 import time |
17 | 17 |
18 from google.appengine.api import app_identity | 18 from google.appengine.api import app_identity |
19 from google.appengine.api import files | 19 from google.appengine.api import files |
20 from google.appengine.api import namespace_manager | 20 from google.appengine.api import namespace_manager |
21 from google.appengine.api import urlfetch | 21 from google.appengine.api import urlfetch |
22 | 22 |
23 from models.private_key import PrivateKey | 23 from models.private_key import PrivateKey |
24 | 24 |
25 import cloudstorage | |
26 | |
25 # The Google Cloud Storage bucket for this app | 27 # The Google Cloud Storage bucket for this app |
26 _BUCKET = "pub.dartlang.org" | 28 _BUCKET = "pub.dartlang.org" |
27 | 29 |
28 # From https://code.google.com/apis/console | 30 # From https://code.google.com/apis/console |
29 _ACCESS_KEY = "818368855108@developer.gserviceaccount.com" | 31 _ACCESS_KEY = "818368855108@developer.gserviceaccount.com" |
30 | 32 |
31 # From https://developers.google.com/storage/docs/authentication | 33 # From https://developers.google.com/storage/docs/authentication |
32 _FULL_CONTROL_SCOPE = "https://www.googleapis.com/auth/devstorage.full_control" | 34 _FULL_CONTROL_SCOPE = "https://www.googleapis.com/auth/devstorage.full_control" |
33 | 35 |
34 # The maximum size (in bytes) of a chunk that can be read from cloud storage at | 36 # The maximum size (in bytes) of a chunk that can be read from cloud storage at |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
206 raise handlers.http_error(500, "Cloud storage %s error: %s\n%s" % ( | 208 raise handlers.http_error(500, "Cloud storage %s error: %s\n%s" % ( |
207 response.status_code, | 209 response.status_code, |
208 xml.find('Code').text, | 210 xml.find('Code').text, |
209 xml.find('Message').text | 211 xml.find('Message').text |
210 )) | 212 )) |
211 | 213 |
212 def delete_object(obj): | 214 def delete_object(obj): |
213 """Deletes an object from cloud storage.""" | 215 """Deletes an object from cloud storage.""" |
214 files.delete(_appengine_object_path(obj)) | 216 files.delete(_appengine_object_path(obj)) |
215 | 217 |
216 def open(obj): | 218 def open(obj): |
Bob Nystrom
2015/03/23 19:41:13
Might be good to leave a comment that this is depr
kustermann
2015/03/24 18:28:20
Done.
It's still used -- I've added a deprecation
| |
217 """Opens an object in cloud storage.""" | 219 """Opens an object in cloud storage.""" |
218 return files.open(_appengine_object_path(obj), 'r') | 220 return files.open(_appengine_object_path(obj), 'r') |
219 | 221 |
222 def open_with_gcs(obj): | |
223 """Opens an object in cloud storage with the GCS library.""" | |
224 return cloudstorage.open(_gcs_appengine_object_path(obj), 'r') | |
225 | |
220 def read(obj): | 226 def read(obj): |
221 """Consumes and returns all data in an object in cloud storage. | 227 """Consumes and returns all data in an object in cloud storage. |
222 | 228 |
223 The data is returned as a StringIO instance, so it may be used in place of a | 229 The data is returned as a StringIO instance, so it may be used in place of a |
224 file. | 230 file. |
225 | 231 |
226 This can be necessary since many operations on the file object itself | 232 This can be necessary since many operations on the file object itself |
227 require a network round trip.""" | 233 require a network round trip.""" |
228 | 234 |
229 with open(obj) as f: | 235 with open_with_gcs(obj) as f: |
230 io = StringIO() | 236 io = StringIO() |
231 data = f.read(_CHUNK_SIZE) | 237 data = f.read(_CHUNK_SIZE) |
232 while data: | 238 while data: |
233 io.write(data) | 239 io.write(data) |
234 data = f.read(_CHUNK_SIZE) | 240 data = f.read(_CHUNK_SIZE) |
235 io.seek(0) | 241 io.seek(0) |
236 return io | 242 return io |
237 | 243 |
238 def object_url(obj): | 244 def object_url(obj): |
239 """Returns the URL for an object in cloud storage.""" | 245 """Returns the URL for an object in cloud storage.""" |
240 if handlers.is_production(): | 246 if handlers.is_production(): |
241 return 'https://storage.googleapis.com/' + _object_path(obj) | 247 return 'https://storage.googleapis.com/' + _object_path(obj) |
242 else: | 248 else: |
243 return '/gs_/' + urllib.quote(obj) | 249 return '/gs_/' + urllib.quote(obj) |
244 | 250 |
245 def _object_path(obj): | 251 def _object_path(obj): |
246 """Returns the path for an object in cloud storage.""" | 252 """Returns the path for an object in cloud storage.""" |
247 ns = namespace_manager.get_namespace() | 253 ns = namespace_manager.get_namespace() |
248 if ns == "": return _BUCKET + '/' + obj | 254 if ns == "": return _BUCKET + '/' + obj |
249 return _BUCKET + '/ns/' + ns + '/' + obj | 255 return _BUCKET + '/ns/' + ns + '/' + obj |
250 | 256 |
251 def _appengine_object_path(obj): | 257 def _appengine_object_path(obj): |
252 """Returns the path for an object for use with the AppEngine APIs.""" | 258 """Returns the path for an object for use with the AppEngine APIs.""" |
253 return '/gs/' + _object_path(obj) | 259 return '/gs/' + _object_path(obj) |
254 | 260 |
261 def _gcs_appengine_object_path(obj): | |
262 """Returns the path for an object for use with the GCS APIs.""" | |
263 return '/' + _object_path(obj) | |
264 | |
255 def _iso8601(secs): | 265 def _iso8601(secs): |
256 """Returns the ISO8601 representation of the given time. | 266 """Returns the ISO8601 representation of the given time. |
257 | 267 |
258 The time should be in seconds past the epoch.""" | 268 The time should be in seconds past the epoch.""" |
259 return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(secs)) | 269 return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(secs)) |
OLD | NEW |