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

Side by Side Diff: boto/storage_uri.py

Issue 8386013: Merging in latest boto. (Closed) Base URL: svn://svn.chromium.org/boto
Patch Set: Redoing vendor drop by deleting and then merging. Created 9 years, 1 month 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
« no previous file with comments | « boto/sqs/queue.py ('k') | boto/sts/__init__.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2010 Google Inc. 1 # Copyright 2010 Google Inc.
2 # Copyright (c) 2011, Nexenta Systems Inc.
2 # 3 #
3 # Permission is hereby granted, free of charge, to any person obtaining a 4 # Permission is hereby granted, free of charge, to any person obtaining a
4 # copy of this software and associated documentation files (the 5 # copy of this software and associated documentation files (the
5 # "Software"), to deal in the Software without restriction, including 6 # "Software"), to deal in the Software without restriction, including
6 # without limitation the rights to use, copy, modify, merge, publish, dis- 7 # without limitation the rights to use, copy, modify, merge, publish, dis-
7 # tribute, sublicense, and/or sell copies of the Software, and to permit 8 # tribute, sublicense, and/or sell copies of the Software, and to permit
8 # persons to whom the Software is furnished to do so, subject to the fol- 9 # persons to whom the Software is furnished to do so, subject to the fol-
9 # lowing conditions: 10 # lowing conditions:
10 # 11 #
11 # The above copyright notice and this permission notice shall be included 12 # The above copyright notice and this permission notice shall be included
12 # in all copies or substantial portions of the Software. 13 # in all copies or substantial portions of the Software.
13 # 14 #
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 17 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 # IN THE SOFTWARE. 21 # IN THE SOFTWARE.
21 22
23 import boto
22 import os 24 import os
23 from boto.exception import BotoClientError 25 from boto.exception import BotoClientError
24 from boto.exception import InvalidUriError 26 from boto.exception import InvalidUriError
25 27
26 28
27 class StorageUri(object): 29 class StorageUri(object):
28 """ 30 """
29 Base class for representing storage provider-independent bucket and 31 Base class for representing storage provider-independent bucket and
30 object name with a shorthand URI-like syntax. 32 object name with a shorthand URI-like syntax.
31 33
32 This is an abstract class: the constructor cannot be called (throws an 34 This is an abstract class: the constructor cannot be called (throws an
33 exception if you try). 35 exception if you try).
34 """ 36 """
35 37
36 connection = None 38 connection = None
39 # Optional args that can be set from one of the concrete subclass
40 # constructors, to change connection behavior (e.g., to override
41 # https_connection_factory).
42 connection_args = None
37 43
38 def __init__(self): 44 def __init__(self):
39 """Uncallable constructor on abstract base StorageUri class. 45 """Uncallable constructor on abstract base StorageUri class.
40 """ 46 """
41 raise BotoClientError('Attempt to instantiate abstract StorageUri ' 47 raise BotoClientError('Attempt to instantiate abstract StorageUri '
42 'class') 48 'class')
43 49
44 def __repr__(self): 50 def __repr__(self):
45 """Returns string representation of URI.""" 51 """Returns string representation of URI."""
46 return self.uri 52 return self.uri
(...skipping 12 matching lines...) Expand all
59 """ 65 """
60 Opens a connection to appropriate provider, depending on provider 66 Opens a connection to appropriate provider, depending on provider
61 portion of URI. Requires Credentials defined in boto config file (see 67 portion of URI. Requires Credentials defined in boto config file (see
62 boto/pyami/config.py). 68 boto/pyami/config.py).
63 @type storage_uri: StorageUri 69 @type storage_uri: StorageUri
64 @param storage_uri: StorageUri specifying a bucket or a bucket+object 70 @param storage_uri: StorageUri specifying a bucket or a bucket+object
65 @rtype: L{AWSAuthConnection<boto.gs.connection.AWSAuthConnection>} 71 @rtype: L{AWSAuthConnection<boto.gs.connection.AWSAuthConnection>}
66 @return: A connection to storage service provider of the given URI. 72 @return: A connection to storage service provider of the given URI.
67 """ 73 """
68 74
75 connection_args = dict(self.connection_args or ())
76 # Use OrdinaryCallingFormat instead of boto-default
77 # SubdomainCallingFormat because the latter changes the hostname
78 # that's checked during cert validation for HTTPS connections,
79 # which will fail cert validation (when cert validation is enabled).
80 # Note: the following import can't be moved up to the start of
81 # this file else it causes a config import failure when run from
82 # the resumable upload/download tests.
83 from boto.s3.connection import OrdinaryCallingFormat
84 connection_args['calling_format'] = OrdinaryCallingFormat()
85 connection_args.update(kwargs)
69 if not self.connection: 86 if not self.connection:
70 if self.scheme == 's3': 87 if self.scheme == 's3':
71 from boto.s3.connection import S3Connection 88 from boto.s3.connection import S3Connection
72 self.connection = S3Connection(access_key_id, 89 self.connection = S3Connection(access_key_id,
73 secret_access_key, **kwargs) 90 secret_access_key,
91 **connection_args)
74 elif self.scheme == 'gs': 92 elif self.scheme == 'gs':
75 from boto.gs.connection import GSConnection 93 from boto.gs.connection import GSConnection
76 self.connection = GSConnection(access_key_id, 94 self.connection = GSConnection(access_key_id,
77 secret_access_key, **kwargs) 95 secret_access_key,
96 **connection_args)
78 elif self.scheme == 'file': 97 elif self.scheme == 'file':
79 from boto.file.connection import FileConnection 98 from boto.file.connection import FileConnection
80 self.connection = FileConnection(self) 99 self.connection = FileConnection(self)
81 else: 100 else:
82 raise InvalidUriError('Unrecognized scheme "%s"' % 101 raise InvalidUriError('Unrecognized scheme "%s"' %
83 self.scheme) 102 self.scheme)
84 self.connection.debug = self.debug 103 self.connection.debug = self.debug
85 return self.connection 104 return self.connection
86 105
87 def delete_key(self, validate=True, headers=None, version_id=None, 106 def delete_key(self, validate=True, headers=None, version_id=None,
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 return canned_acls 168 return canned_acls
150 169
151 170
152 class BucketStorageUri(StorageUri): 171 class BucketStorageUri(StorageUri):
153 """ 172 """
154 StorageUri subclass that handles bucket storage providers. 173 StorageUri subclass that handles bucket storage providers.
155 Callers should instantiate this class by calling boto.storage_uri(). 174 Callers should instantiate this class by calling boto.storage_uri().
156 """ 175 """
157 176
158 def __init__(self, scheme, bucket_name=None, object_name=None, 177 def __init__(self, scheme, bucket_name=None, object_name=None,
159 debug=0): 178 debug=0, connection_args=None):
160 """Instantiate a BucketStorageUri from scheme,bucket,object tuple. 179 """Instantiate a BucketStorageUri from scheme,bucket,object tuple.
161 180
162 @type scheme: string 181 @type scheme: string
163 @param scheme: URI scheme naming the storage provider (gs, s3, etc.) 182 @param scheme: URI scheme naming the storage provider (gs, s3, etc.)
164 @type bucket_name: string 183 @type bucket_name: string
165 @param bucket_name: bucket name 184 @param bucket_name: bucket name
166 @type object_name: string 185 @type object_name: string
167 @param object_name: object name 186 @param object_name: object name
168 @type debug: int 187 @type debug: int
169 @param debug: debug level to pass in to connection (range 0..2) 188 @param debug: debug level to pass in to connection (range 0..2)
189 @type connection_args: map
190 @param connection_args: optional map containing args to be
191 passed to {S3,GS}Connection constructor (e.g., to override
192 https_connection_factory).
170 193
171 After instantiation the components are available in the following 194 After instantiation the components are available in the following
172 fields: uri, scheme, bucket_name, object_name. 195 fields: uri, scheme, bucket_name, object_name.
173 """ 196 """
174 197
175 self.scheme = scheme 198 self.scheme = scheme
176 self.bucket_name = bucket_name 199 self.bucket_name = bucket_name
177 self.object_name = object_name 200 self.object_name = object_name
201 if connection_args:
202 self.connection_args = connection_args
178 if self.bucket_name and self.object_name: 203 if self.bucket_name and self.object_name:
179 self.uri = ('%s://%s/%s' % (self.scheme, self.bucket_name, 204 self.uri = ('%s://%s/%s' % (self.scheme, self.bucket_name,
180 self.object_name)) 205 self.object_name))
181 elif self.bucket_name: 206 elif self.bucket_name:
182 self.uri = ('%s://%s/' % (self.scheme, self.bucket_name)) 207 self.uri = ('%s://%s/' % (self.scheme, self.bucket_name))
183 else: 208 else:
184 self.uri = ('%s://' % self.scheme) 209 self.uri = ('%s://' % self.scheme)
185 self.debug = debug 210 self.debug = debug
186 211
187 def clone_replace_name(self, new_name): 212 def clone_replace_name(self, new_name):
(...skipping 12 matching lines...) Expand all
200 def get_acl(self, validate=True, headers=None, version_id=None): 225 def get_acl(self, validate=True, headers=None, version_id=None):
201 if not self.bucket_name: 226 if not self.bucket_name:
202 raise InvalidUriError('get_acl on bucket-less URI (%s)' % self.uri) 227 raise InvalidUriError('get_acl on bucket-less URI (%s)' % self.uri)
203 bucket = self.get_bucket(validate, headers) 228 bucket = self.get_bucket(validate, headers)
204 # This works for both bucket- and object- level ACLs (former passes 229 # This works for both bucket- and object- level ACLs (former passes
205 # key_name=None): 230 # key_name=None):
206 acl = bucket.get_acl(self.object_name, headers, version_id) 231 acl = bucket.get_acl(self.object_name, headers, version_id)
207 self.check_response(acl, 'acl', self.uri) 232 self.check_response(acl, 'acl', self.uri)
208 return acl 233 return acl
209 234
235 def get_location(self, validate=True, headers=None):
236 if not self.bucket_name:
237 raise InvalidUriError('get_location on bucket-less URI (%s)' %
238 self.uri)
239 bucket = self.get_bucket(validate, headers)
240 return bucket.get_location()
241
242 def get_subresource(self, subresource, validate=True, headers=None,
243 version_id=None):
244 if not self.bucket_name:
245 raise InvalidUriError(
246 'get_subresource on bucket-less URI (%s)' % self.uri)
247 bucket = self.get_bucket(validate, headers)
248 return bucket.get_subresource(subresource, self.object_name, headers,
249 version_id)
250
210 def add_group_email_grant(self, permission, email_address, recursive=False, 251 def add_group_email_grant(self, permission, email_address, recursive=False,
211 validate=True, headers=None): 252 validate=True, headers=None):
212 if self.scheme != 'gs': 253 if self.scheme != 'gs':
213 raise ValueError('add_group_email_grant() not supported for %s ' 254 raise ValueError('add_group_email_grant() not supported for %s '
214 'URIs.' % self.scheme) 255 'URIs.' % self.scheme)
215 if self.object_name: 256 if self.object_name:
216 if recursive: 257 if recursive:
217 raise ValueError('add_group_email_grant() on key-ful URI cannot ' 258 raise ValueError('add_group_email_grant() on key-ful URI cannot '
218 'specify recursive=True') 259 'specify recursive=True')
219 key = self.get_key(validate, headers) 260 key = self.get_key(validate, headers)
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 352
312 def set_canned_acl(self, acl_str, validate=True, headers=None, 353 def set_canned_acl(self, acl_str, validate=True, headers=None,
313 version_id=None): 354 version_id=None):
314 if not self.object_name: 355 if not self.object_name:
315 raise InvalidUriError('set_canned_acl on object-less URI (%s)' % 356 raise InvalidUriError('set_canned_acl on object-less URI (%s)' %
316 self.uri) 357 self.uri)
317 key = self.get_key(validate, headers) 358 key = self.get_key(validate, headers)
318 self.check_response(key, 'key', self.uri) 359 self.check_response(key, 'key', self.uri)
319 key.set_canned_acl(acl_str, headers, version_id) 360 key.set_canned_acl(acl_str, headers, version_id)
320 361
362 def set_subresource(self, subresource, value, validate=True, headers=None,
363 version_id=None):
364 if not self.bucket_name:
365 raise InvalidUriError(
366 'set_subresource on bucket-less URI (%s)' % self.uri)
367 bucket = self.get_bucket(validate, headers)
368 bucket.set_subresource(subresource, value, self.object_name, headers,
369 version_id)
370
321 def set_contents_from_string(self, s, headers=None, replace=True, 371 def set_contents_from_string(self, s, headers=None, replace=True,
322 cb=None, num_cb=10, policy=None, md5=None, 372 cb=None, num_cb=10, policy=None, md5=None,
323 reduced_redundancy=False): 373 reduced_redundancy=False):
324 key = self.new_key(headers=headers) 374 key = self.new_key(headers=headers)
325 key.set_contents_from_string(s, headers, replace, cb, num_cb, policy, 375 key.set_contents_from_string(s, headers, replace, cb, num_cb, policy,
326 md5, reduced_redundancy) 376 md5, reduced_redundancy)
327 377
378 def enable_logging(self, target_bucket, target_prefix=None,
379 canned_acl=None, validate=True, headers=None,
380 version_id=None):
381 if not self.bucket_name:
382 raise InvalidUriError(
383 'disable_logging on bucket-less URI (%s)' % self.uri)
384 bucket = self.get_bucket(validate, headers)
385 bucket.enable_logging(target_bucket, target_prefix, headers=headers,
386 canned_acl=canned_acl)
387
388 def disable_logging(self, validate=True, headers=None, version_id=None):
389 if not self.bucket_name:
390 raise InvalidUriError(
391 'disable_logging on bucket-less URI (%s)' % self.uri)
392 bucket = self.get_bucket(validate, headers)
393 bucket.disable_logging(headers=headers)
394
328 395
329 396
330 class FileStorageUri(StorageUri): 397 class FileStorageUri(StorageUri):
331 """ 398 """
332 StorageUri subclass that handles files in the local file system. 399 StorageUri subclass that handles files in the local file system.
333 Callers should instantiate this class by calling boto.storage_uri(). 400 Callers should instantiate this class by calling boto.storage_uri().
334 401
335 See file/README about how we map StorageUri operations onto a file system. 402 See file/README about how we map StorageUri operations onto a file system.
336 """ 403 """
337 404
338 def __init__(self, object_name, debug): 405 def __init__(self, object_name, debug, is_stream=False):
339 """Instantiate a FileStorageUri from a path name. 406 """Instantiate a FileStorageUri from a path name.
340 407
341 @type object_name: string 408 @type object_name: string
342 @param object_name: object name 409 @param object_name: object name
343 @type debug: boolean 410 @type debug: boolean
344 @param debug: whether to enable debugging on this StorageUri 411 @param debug: whether to enable debugging on this StorageUri
345 412
346 After instantiation the components are available in the following 413 After instantiation the components are available in the following
347 fields: uri, scheme, bucket_name (always blank for this "anonymous" 414 fields: uri, scheme, bucket_name (always blank for this "anonymous"
348 bucket), object_name. 415 bucket), object_name.
349 """ 416 """
350 417
351 self.scheme = 'file' 418 self.scheme = 'file'
352 self.bucket_name = '' 419 self.bucket_name = ''
353 self.object_name = object_name 420 self.object_name = object_name
354 self.uri = 'file://' + object_name 421 self.uri = 'file://' + object_name
355 self.debug = debug 422 self.debug = debug
423 self.stream = is_stream
356 424
357 def clone_replace_name(self, new_name): 425 def clone_replace_name(self, new_name):
358 """Instantiate a FileStorageUri from the current FileStorageUri, 426 """Instantiate a FileStorageUri from the current FileStorageUri,
359 but replacing the object_name. 427 but replacing the object_name.
360 428
361 @type new_name: string 429 @type new_name: string
362 @param new_name: new object name 430 @param new_name: new object name
363 """ 431 """
364 return FileStorageUri(new_name, self.debug) 432 return FileStorageUri(new_name, self.debug, self.stream)
365 433
366 def names_container(self): 434 def names_container(self):
367 """Returns True if this URI names a directory. 435 """Returns True if this URI is not representing input/output stream
436 and names a directory.
368 """ 437 """
369 return os.path.isdir(self.object_name) 438 if not self.stream:
439 return os.path.isdir(self.object_name)
440 else:
441 return False
370 442
371 def names_singleton(self): 443 def names_singleton(self):
372 """Returns True if this URI names a file. 444 """Returns True if this URI names a file or
445 if URI represents input/output stream.
373 """ 446 """
374 return os.path.isfile(self.object_name) 447 if self.stream:
448 return True
449 else:
450 return os.path.isfile(self.object_name)
375 451
376 def is_file_uri(self): 452 def is_file_uri(self):
377 return True 453 return True
378 454
379 def is_cloud_uri(self): 455 def is_cloud_uri(self):
380 return False 456 return False
457
458 def is_stream(self):
459 """Retruns True if this URI represents input/output stream.
460 """
461 return self.stream
OLDNEW
« no previous file with comments | « boto/sqs/queue.py ('k') | boto/sts/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698