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

Unified Diff: third_party/boto/boto/s3/connection.py

Issue 698893003: Update checked in version of gsutil to version 4.6 (Closed) Base URL: http://dart.googlecode.com/svn/third_party/gsutil/
Patch Set: Created 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/boto/boto/s3/bucket.py ('k') | third_party/boto/boto/s3/key.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/boto/boto/s3/connection.py
===================================================================
--- third_party/boto/boto/s3/connection.py (revision 33376)
+++ third_party/boto/boto/s3/connection.py (working copy)
@@ -148,6 +148,16 @@
CNNorth1 = 'cn-north-1'
+class NoHostProvided(object):
+ # An identifying object to help determine whether the user provided a
+ # ``host`` or not. Never instantiated.
+ pass
+
+
+class HostRequiredError(BotoClientError):
+ pass
+
+
class S3Connection(AWSAuthConnection):
DefaultHost = boto.config.get('s3', 'host', 's3.amazonaws.com')
@@ -157,11 +167,15 @@
def __init__(self, aws_access_key_id=None, aws_secret_access_key=None,
is_secure=True, port=None, proxy=None, proxy_port=None,
proxy_user=None, proxy_pass=None,
- host=DefaultHost, debug=0, https_connection_factory=None,
+ host=NoHostProvided, debug=0, https_connection_factory=None,
calling_format=DefaultCallingFormat, path='/',
provider='aws', bucket_class=Bucket, security_token=None,
suppress_consec_slashes=True, anon=False,
- validate_certs=None):
+ validate_certs=None, profile_name=None):
+ no_host_provided = False
+ if host is NoHostProvided:
+ no_host_provided = True
+ host = self.DefaultHost
if isinstance(calling_format, basestring):
calling_format=boto.utils.find_class(calling_format)()
self.calling_format = calling_format
@@ -173,7 +187,14 @@
debug=debug, https_connection_factory=https_connection_factory,
path=path, provider=provider, security_token=security_token,
suppress_consec_slashes=suppress_consec_slashes,
- validate_certs=validate_certs)
+ validate_certs=validate_certs, profile_name=profile_name)
+ # We need to delay until after the call to ``super`` before checking
+ # to see if SigV4 is in use.
+ if no_host_provided:
+ if 'hmac-v4-s3' in self._required_auth_capability():
+ raise HostRequiredError(
+ "When using SigV4, you must specify a 'host' parameter."
+ )
@detect_potential_s3sigv4
def _required_auth_capability(self):
@@ -329,9 +350,34 @@
return {"action": url, "fields": fields}
+ def generate_url_sigv4(self, expires_in, method, bucket='', key='',
+ headers=None, force_http=False,
+ response_headers=None, version_id=None,
+ iso_date=None):
+ path = self.calling_format.build_path_base(bucket, key)
+ auth_path = self.calling_format.build_auth_path(bucket, key)
+ host = self.calling_format.build_host(self.server_name(), bucket)
+
+ params = {}
+ if version_id is not None:
+ params['VersionId'] = version_id
+
+ http_request = self.build_base_http_request(method, path, auth_path,
+ headers=headers, host=host,
+ params=params)
+
+ return self._auth_handler.presign(http_request, expires_in,
+ iso_date=iso_date)
+
def generate_url(self, expires_in, method, bucket='', key='', headers=None,
query_auth=True, force_http=False, response_headers=None,
expires_in_absolute=False, version_id=None):
+ if self._auth_handler.capability[0] == 'hmac-v4-s3':
+ # Handle the special sigv4 case
+ return self.generate_url_sigv4(expires_in, method, bucket=bucket,
+ key=key, headers=headers, force_http=force_http,
+ response_headers=response_headers, version_id=version_id)
+
headers = headers or {}
if expires_in_absolute:
expires = int(expires_in)
@@ -418,6 +464,23 @@
``S3Connection.lookup`` method, which will either return a valid bucket
or ``None``.
+ If ``validate=False`` is passed, no request is made to the service (no
+ charge/communication delay). This is only safe to do if you are **sure**
+ the bucket exists.
+
+ If the default ``validate=True`` is passed, a request is made to the
+ service to ensure the bucket exists. Prior to Boto v2.25.0, this fetched
+ a list of keys (but with a max limit set to ``0``, always returning an empty
+ list) in the bucket (& included better error messages), at an
+ increased expense. As of Boto v2.25.0, this now performs a HEAD request
+ (less expensive but worse error messages).
+
+ If you were relying on parsing the error message before, you should call
+ something like::
+
+ bucket = conn.get_bucket('<bucket_name>', validate=False)
+ bucket.get_all_keys(maxkeys=0)
+
:type bucket_name: string
:param bucket_name: The name of the bucket
@@ -426,14 +489,59 @@
AWS.
:type validate: boolean
- :param validate: If ``True``, it will try to fetch all keys within the
- given bucket. (Default: ``True``)
+ :param validate: If ``True``, it will try to verify the bucket exists
+ on the service-side. (Default: ``True``)
"""
- bucket = self.bucket_class(self, bucket_name)
if validate:
- bucket.get_all_keys(headers, maxkeys=0)
- return bucket
+ return self.head_bucket(bucket_name, headers=headers)
+ else:
+ return self.bucket_class(self, bucket_name)
+ def head_bucket(self, bucket_name, headers=None):
+ """
+ Determines if a bucket exists by name.
+
+ If the bucket does not exist, an ``S3ResponseError`` will be raised.
+
+ :type bucket_name: string
+ :param bucket_name: The name of the bucket
+
+ :type headers: dict
+ :param headers: Additional headers to pass along with the request to
+ AWS.
+
+ :returns: A <Bucket> object
+ """
+ response = self.make_request('HEAD', bucket_name, headers=headers)
+ body = response.read()
+ if response.status == 200:
+ return self.bucket_class(self, bucket_name)
+ elif response.status == 403:
+ # For backward-compatibility, we'll populate part of the exception
+ # with the most-common default.
+ err = self.provider.storage_response_error(
+ response.status,
+ response.reason,
+ body
+ )
+ err.error_code = 'AccessDenied'
+ err.error_message = 'Access Denied'
+ raise err
+ elif response.status == 404:
+ # For backward-compatibility, we'll populate part of the exception
+ # with the most-common default.
+ err = self.provider.storage_response_error(
+ response.status,
+ response.reason,
+ body
+ )
+ err.error_code = 'NoSuchBucket'
+ err.error_message = 'The specified bucket does not exist'
+ raise err
+ else:
+ raise self.provider.storage_response_error(
+ response.status, response.reason, body)
+
def lookup(self, bucket_name, validate=True, headers=None):
"""
Attempts to get a bucket from S3.
« no previous file with comments | « third_party/boto/boto/s3/bucket.py ('k') | third_party/boto/boto/s3/key.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698