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

Unified Diff: third_party/gsutil/boto/boto/gs/bucket.py

Issue 12317103: Added gsutil to depot tools (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 7 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/gsutil/boto/boto/gs/acl.py ('k') | third_party/gsutil/boto/boto/gs/bucketlistresultset.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/gsutil/boto/boto/gs/bucket.py
diff --git a/third_party/gsutil/boto/boto/gs/bucket.py b/third_party/gsutil/boto/boto/gs/bucket.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b61f82276005c7381605078f481ae9f1ad15ddb
--- /dev/null
+++ b/third_party/gsutil/boto/boto/gs/bucket.py
@@ -0,0 +1,870 @@
+# Copyright 2010 Google Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+import urllib
+import xml.sax
+
+import boto
+from boto import handler
+from boto.resultset import ResultSet
+from boto.exception import InvalidAclError
+from boto.gs.acl import ACL, CannedACLStrings
+from boto.gs.acl import SupportedPermissions as GSPermissions
+from boto.gs.bucketlistresultset import VersionedBucketListResultSet
+from boto.gs.cors import Cors
+from boto.gs.key import Key as GSKey
+from boto.s3.acl import Policy
+from boto.s3.bucket import Bucket as S3Bucket
+
+# constants for http query args
+DEF_OBJ_ACL = 'defaultObjectAcl'
+STANDARD_ACL = 'acl'
+CORS_ARG = 'cors'
+
+class Bucket(S3Bucket):
+ """Represents a Google Cloud Storage bucket."""
+
+ VersioningBody = ('<?xml version="1.0" encoding="UTF-8"?>\n'
+ '<VersioningConfiguration><Status>%s</Status>'
+ '</VersioningConfiguration>')
+ WebsiteBody = ('<?xml version="1.0" encoding="UTF-8"?>\n'
+ '<WebsiteConfiguration>%s%s</WebsiteConfiguration>')
+ WebsiteMainPageFragment = '<MainPageSuffix>%s</MainPageSuffix>'
+ WebsiteErrorFragment = '<NotFoundPage>%s</NotFoundPage>'
+
+ def __init__(self, connection=None, name=None, key_class=GSKey):
+ super(Bucket, self).__init__(connection, name, key_class)
+
+ def startElement(self, name, attrs, connection):
+ return None
+
+ def endElement(self, name, value, connection):
+ if name == 'Name':
+ self.name = value
+ elif name == 'CreationDate':
+ self.creation_date = value
+ else:
+ setattr(self, name, value)
+
+ def get_key(self, key_name, headers=None, version_id=None,
+ response_headers=None, generation=None):
+ """Returns a Key instance for an object in this bucket.
+
+ Note that this method uses a HEAD request to check for the existence of
+ the key.
+
+ :type key_name: string
+ :param key_name: The name of the key to retrieve
+
+ :type response_headers: dict
+ :param response_headers: A dictionary containing HTTP
+ headers/values that will override any headers associated
+ with the stored object in the response. See
+ http://goo.gl/06N3b for details.
+
+ :type version_id: string
+ :param version_id: Unused in this subclass.
+
+ :type generation: int
+ :param generation: A specific generation number to fetch the key at. If
+ not specified, the latest generation is fetched.
+
+ :rtype: :class:`boto.gs.key.Key`
+ :returns: A Key object from this bucket.
+ """
+ query_args_l = []
+ if generation:
+ query_args_l.append('generation=%s' % generation)
+ if response_headers:
+ for rk, rv in response_headers.iteritems():
+ query_args_l.append('%s=%s' % (rk, urllib.quote(rv)))
+
+ key, resp = self._get_key_internal(key_name, headers,
+ query_args_l=query_args_l)
+ return key
+
+ def copy_key(self, new_key_name, src_bucket_name, src_key_name,
+ metadata=None, src_version_id=None, storage_class='STANDARD',
+ preserve_acl=False, encrypt_key=False, headers=None,
+ query_args=None, src_generation=None):
+ """Create a new key in the bucket by copying an existing key.
+
+ :type new_key_name: string
+ :param new_key_name: The name of the new key
+
+ :type src_bucket_name: string
+ :param src_bucket_name: The name of the source bucket
+
+ :type src_key_name: string
+ :param src_key_name: The name of the source key
+
+ :type src_generation: int
+ :param src_generation: The generation number of the source key to copy.
+ If not specified, the latest generation is copied.
+
+ :type metadata: dict
+ :param metadata: Metadata to be associated with new key. If
+ metadata is supplied, it will replace the metadata of the
+ source key being copied. If no metadata is supplied, the
+ source key's metadata will be copied to the new key.
+
+ :type version_id: string
+ :param version_id: Unused in this subclass.
+
+ :type storage_class: string
+ :param storage_class: The storage class of the new key. By
+ default, the new key will use the standard storage class.
+ Possible values are: STANDARD | DURABLE_REDUCED_AVAILABILITY
+
+ :type preserve_acl: bool
+ :param preserve_acl: If True, the ACL from the source key will
+ be copied to the destination key. If False, the
+ destination key will have the default ACL. Note that
+ preserving the ACL in the new key object will require two
+ additional API calls to GCS, one to retrieve the current
+ ACL and one to set that ACL on the new object. If you
+ don't care about the ACL (or if you have a default ACL set
+ on the bucket), a value of False will be significantly more
+ efficient.
+
+ :type encrypt_key: bool
+ :param encrypt_key: Included for compatibility with S3. This argument is
+ ignored.
+
+ :type headers: dict
+ :param headers: A dictionary of header name/value pairs.
+
+ :type query_args: string
+ :param query_args: A string of additional querystring arguments
+ to append to the request
+
+ :rtype: :class:`boto.gs.key.Key`
+ :returns: An instance of the newly created key object
+ """
+ if src_generation:
+ headers = headers or {}
+ headers['x-goog-copy-source-generation'] = str(src_generation)
+ return super(Bucket, self).copy_key(
+ new_key_name, src_bucket_name, src_key_name, metadata=metadata,
+ storage_class=storage_class, preserve_acl=preserve_acl,
+ encrypt_key=encrypt_key, headers=headers, query_args=query_args)
+
+ def list_versions(self, prefix='', delimiter='', marker='',
+ generation_marker='', headers=None):
+ """
+ List versioned objects within a bucket. This returns an
+ instance of an VersionedBucketListResultSet that automatically
+ handles all of the result paging, etc. from GCS. You just need
+ to keep iterating until there are no more results. Called
+ with no arguments, this will return an iterator object across
+ all keys within the bucket.
+
+ :type prefix: string
+ :param prefix: allows you to limit the listing to a particular
+ prefix. For example, if you call the method with
+ prefix='/foo/' then the iterator will only cycle through
+ the keys that begin with the string '/foo/'.
+
+ :type delimiter: string
+ :param delimiter: can be used in conjunction with the prefix
+ to allow you to organize and browse your keys
+ hierarchically. See:
+ https://developers.google.com/storage/docs/reference-headers#delimiter
+ for more details.
+
+ :type marker: string
+ :param marker: The "marker" of where you are in the result set
+
+ :type generation_marker: string
+ :param generation_marker: The "generation marker" of where you are in
+ the result set.
+
+ :type headers: dict
+ :param headers: A dictionary of header name/value pairs.
+
+ :rtype:
+ :class:`boto.gs.bucketlistresultset.VersionedBucketListResultSet`
+ :return: an instance of a BucketListResultSet that handles paging, etc.
+ """
+ return VersionedBucketListResultSet(self, prefix, delimiter,
+ marker, generation_marker,
+ headers)
+
+ def delete_key(self, key_name, headers=None, version_id=None,
+ mfa_token=None, generation=None):
+ """
+ Deletes a key from the bucket.
+
+ :type key_name: string
+ :param key_name: The key name to delete
+
+ :type headers: dict
+ :param headers: A dictionary of header name/value pairs.
+
+ :type version_id: string
+ :param version_id: Unused in this subclass.
+
+ :type mfa_token: tuple or list of strings
+ :param mfa_token: Unused in this subclass.
+
+ :type generation: int
+ :param generation: The generation number of the key to delete. If not
+ specified, the latest generation number will be deleted.
+
+ :rtype: :class:`boto.gs.key.Key`
+ :returns: A key object holding information on what was
+ deleted.
+ """
+ query_args_l = []
+ if generation:
+ query_args_l.append('generation=%s' % generation)
+ self._delete_key_internal(key_name, headers=headers,
+ version_id=version_id, mfa_token=mfa_token,
+ query_args_l=query_args_l)
+
+ def set_acl(self, acl_or_str, key_name='', headers=None, version_id=None,
+ generation=None, if_generation=None, if_metageneration=None):
+ """Sets or changes a bucket's or key's ACL.
+
+ :type acl_or_str: string or :class:`boto.gs.acl.ACL`
+ :param acl_or_str: A canned ACL string (see
+ :data:`~.gs.acl.CannedACLStrings`) or an ACL object.
+
+ :type key_name: string
+ :param key_name: A key name within the bucket to set the ACL for. If not
+ specified, the ACL for the bucket will be set.
+
+ :type headers: dict
+ :param headers: Additional headers to set during the request.
+
+ :type version_id: string
+ :param version_id: Unused in this subclass.
+
+ :type generation: int
+ :param generation: If specified, sets the ACL for a specific generation
+ of a versioned object. If not specified, the current version is
+ modified.
+
+ :type if_generation: int
+ :param if_generation: (optional) If set to a generation number, the acl
+ will only be updated if its current generation number is this value.
+
+ :type if_metageneration: int
+ :param if_metageneration: (optional) If set to a metageneration number,
+ the acl will only be updated if its current metageneration number is
+ this value.
+ """
+ if isinstance(acl_or_str, Policy):
+ raise InvalidAclError('Attempt to set S3 Policy on GS ACL')
+ elif isinstance(acl_or_str, ACL):
+ self.set_xml_acl(acl_or_str.to_xml(), key_name, headers=headers,
+ generation=generation,
+ if_generation=if_generation,
+ if_metageneration=if_metageneration)
+ else:
+ self.set_canned_acl(acl_or_str, key_name, headers=headers,
+ generation=generation,
+ if_generation=if_generation,
+ if_metageneration=if_metageneration)
+
+ def set_def_acl(self, acl_or_str, headers=None):
+ """Sets or changes a bucket's default ACL.
+
+ :type acl_or_str: string or :class:`boto.gs.acl.ACL`
+ :param acl_or_str: A canned ACL string (see
+ :data:`~.gs.acl.CannedACLStrings`) or an ACL object.
+
+ :type headers: dict
+ :param headers: Additional headers to set during the request.
+ """
+ if isinstance(acl_or_str, Policy):
+ raise InvalidAclError('Attempt to set S3 Policy on GS ACL')
+ elif isinstance(acl_or_str, ACL):
+ self.set_def_xml_acl(acl_or_str.to_xml(), headers=headers)
+ else:
+ self.set_def_canned_acl(acl_or_str, headers=headers)
+
+ def _get_xml_acl_helper(self, key_name, headers, query_args):
+ """Provides common functionality for get_xml_acl and _get_acl_helper."""
+ response = self.connection.make_request('GET', self.name, key_name,
+ query_args=query_args,
+ headers=headers)
+ body = response.read()
+ if response.status != 200:
+ raise self.connection.provider.storage_response_error(
+ response.status, response.reason, body)
+ return body
+
+ def _get_acl_helper(self, key_name, headers, query_args):
+ """Provides common functionality for get_acl and get_def_acl."""
+ body = self._get_xml_acl_helper(key_name, headers, query_args)
+ acl = ACL(self)
+ h = handler.XmlHandler(acl, self)
+ xml.sax.parseString(body, h)
+ return acl
+
+ def get_acl(self, key_name='', headers=None, version_id=None,
+ generation=None):
+ """Returns the ACL of the bucket or an object in the bucket.
+
+ :param str key_name: The name of the object to get the ACL for. If not
+ specified, the ACL for the bucket will be returned.
+
+ :param dict headers: Additional headers to set during the request.
+
+ :type version_id: string
+ :param version_id: Unused in this subclass.
+
+ :param int generation: If specified, gets the ACL for a specific
+ generation of a versioned object. If not specified, the current
+ version is returned. This parameter is only valid when retrieving
+ the ACL of an object, not a bucket.
+
+ :rtype: :class:`.gs.acl.ACL`
+ """
+ query_args = STANDARD_ACL
+ if generation:
+ query_args += '&generation=%s' % generation
+ return self._get_acl_helper(key_name, headers, query_args)
+
+ def get_xml_acl(self, key_name='', headers=None, version_id=None,
+ generation=None):
+ """Returns the ACL string of the bucket or an object in the bucket.
+
+ :param str key_name: The name of the object to get the ACL for. If not
+ specified, the ACL for the bucket will be returned.
+
+ :param dict headers: Additional headers to set during the request.
+
+ :type version_id: string
+ :param version_id: Unused in this subclass.
+
+ :param int generation: If specified, gets the ACL for a specific
+ generation of a versioned object. If not specified, the current
+ version is returned. This parameter is only valid when retrieving
+ the ACL of an object, not a bucket.
+
+ :rtype: str
+ """
+ query_args = STANDARD_ACL
+ if generation:
+ query_args += '&generation=%s' % generation
+ return self._get_xml_acl_helper(key_name, headers, query_args)
+
+ def get_def_acl(self, headers=None):
+ """Returns the bucket's default ACL.
+
+ :param dict headers: Additional headers to set during the request.
+
+ :rtype: :class:`.gs.acl.ACL`
+ """
+ return self._get_acl_helper('', headers, DEF_OBJ_ACL)
+
+ def _set_acl_helper(self, acl_or_str, key_name, headers, query_args,
+ generation, if_generation, if_metageneration,
+ canned=False):
+ """Provides common functionality for set_acl, set_xml_acl,
+ set_canned_acl, set_def_acl, set_def_xml_acl, and
+ set_def_canned_acl()."""
+
+ headers = headers or {}
+ data = ''
+ if canned:
+ headers[self.connection.provider.acl_header] = acl_or_str
+ else:
+ data = acl_or_str.encode('UTF-8')
+
+ if generation:
+ query_args += '&generation=%s' % generation
+
+ if if_metageneration is not None and if_generation is None:
+ raise ValueError("Received if_metageneration argument with no "
+ "if_generation argument. A meta-generation has no "
+ "meaning without a content generation.")
+ if not key_name and (if_generation or if_metageneration):
+ raise ValueError("Received if_generation or if_metageneration "
+ "parameter while setting the ACL of a bucket.")
+ if if_generation is not None:
+ headers['x-goog-if-generation-match'] = str(if_generation)
+ if if_metageneration is not None:
+ headers['x-goog-if-metageneration-match'] = str(if_metageneration)
+
+ response = self.connection.make_request('PUT', self.name, key_name,
+ data=data, headers=headers, query_args=query_args)
+ body = response.read()
+ if response.status != 200:
+ raise self.connection.provider.storage_response_error(
+ response.status, response.reason, body)
+
+ def set_xml_acl(self, acl_str, key_name='', headers=None, version_id=None,
+ query_args='acl', generation=None, if_generation=None,
+ if_metageneration=None):
+ """Sets a bucket's or objects's ACL to an XML string.
+
+ :type acl_str: string
+ :param acl_str: A string containing the ACL XML.
+
+ :type key_name: string
+ :param key_name: A key name within the bucket to set the ACL for. If not
+ specified, the ACL for the bucket will be set.
+
+ :type headers: dict
+ :param headers: Additional headers to set during the request.
+
+ :type version_id: string
+ :param version_id: Unused in this subclass.
+
+ :type query_args: str
+ :param query_args: The query parameters to pass with the request.
+
+ :type generation: int
+ :param generation: If specified, sets the ACL for a specific generation
+ of a versioned object. If not specified, the current version is
+ modified.
+
+ :type if_generation: int
+ :param if_generation: (optional) If set to a generation number, the acl
+ will only be updated if its current generation number is this value.
+
+ :type if_metageneration: int
+ :param if_metageneration: (optional) If set to a metageneration number,
+ the acl will only be updated if its current metageneration number is
+ this value.
+ """
+ return self._set_acl_helper(acl_str, key_name=key_name, headers=headers,
+ query_args=query_args,
+ generation=generation,
+ if_generation=if_generation,
+ if_metageneration=if_metageneration)
+
+ def set_canned_acl(self, acl_str, key_name='', headers=None,
+ version_id=None, generation=None, if_generation=None,
+ if_metageneration=None):
+ """Sets a bucket's or objects's ACL using a predefined (canned) value.
+
+ :type acl_str: string
+ :param acl_str: A canned ACL string. See
+ :data:`~.gs.acl.CannedACLStrings`.
+
+ :type key_name: string
+ :param key_name: A key name within the bucket to set the ACL for. If not
+ specified, the ACL for the bucket will be set.
+
+ :type headers: dict
+ :param headers: Additional headers to set during the request.
+
+ :type version_id: string
+ :param version_id: Unused in this subclass.
+
+ :type generation: int
+ :param generation: If specified, sets the ACL for a specific generation
+ of a versioned object. If not specified, the current version is
+ modified.
+
+ :type if_generation: int
+ :param if_generation: (optional) If set to a generation number, the acl
+ will only be updated if its current generation number is this value.
+
+ :type if_metageneration: int
+ :param if_metageneration: (optional) If set to a metageneration number,
+ the acl will only be updated if its current metageneration number is
+ this value.
+ """
+ if acl_str not in CannedACLStrings:
+ raise ValueError("Provided canned ACL string (%s) is not valid."
+ % acl_str)
+ query_args = STANDARD_ACL
+ return self._set_acl_helper(acl_str, key_name, headers, query_args,
+ generation, if_generation,
+ if_metageneration, canned=True)
+
+ def set_def_canned_acl(self, acl_str, headers=None):
+ """Sets a bucket's default ACL using a predefined (canned) value.
+
+ :type acl_str: string
+ :param acl_str: A canned ACL string. See
+ :data:`~.gs.acl.CannedACLStrings`.
+
+ :type headers: dict
+ :param headers: Additional headers to set during the request.
+ """
+ if acl_str not in CannedACLStrings:
+ raise ValueError("Provided canned ACL string (%s) is not valid."
+ % acl_str)
+ query_args = DEF_OBJ_ACL
+ return self._set_acl_helper(acl_str, '', headers, query_args,
+ generation=None, if_generation=None,
+ if_metageneration=None, canned=True)
+
+ def set_def_xml_acl(self, acl_str, headers=None):
+ """Sets a bucket's default ACL to an XML string.
+
+ :type acl_str: string
+ :param acl_str: A string containing the ACL XML.
+
+ :type headers: dict
+ :param headers: Additional headers to set during the request.
+ """
+ return self.set_xml_acl(acl_str, '', headers,
+ query_args=DEF_OBJ_ACL)
+
+ def get_cors(self, headers=None):
+ """Returns a bucket's CORS XML document.
+
+ :param dict headers: Additional headers to send with the request.
+ :rtype: :class:`~.cors.Cors`
+ """
+ response = self.connection.make_request('GET', self.name,
+ query_args=CORS_ARG,
+ headers=headers)
+ body = response.read()
+ if response.status == 200:
+ # Success - parse XML and return Cors object.
+ cors = Cors()
+ h = handler.XmlHandler(cors, self)
+ xml.sax.parseString(body, h)
+ return cors
+ else:
+ raise self.connection.provider.storage_response_error(
+ response.status, response.reason, body)
+
+ def set_cors(self, cors, headers=None):
+ """Sets a bucket's CORS XML document.
+
+ :param str cors: A string containing the CORS XML.
+ :param dict headers: Additional headers to send with the request.
+ """
+ cors_xml = cors.encode('UTF-8')
+ response = self.connection.make_request('PUT', self.name,
+ data=cors_xml,
+ query_args=CORS_ARG,
+ headers=headers)
+ body = response.read()
+ if response.status != 200:
+ raise self.connection.provider.storage_response_error(
+ response.status, response.reason, body)
+
+ def get_storage_class(self):
+ """
+ Returns the StorageClass for the bucket.
+
+ :rtype: str
+ :return: The StorageClass for the bucket.
+ """
+ response = self.connection.make_request('GET', self.name,
+ query_args='storageClass')
+ body = response.read()
+ if response.status == 200:
+ rs = ResultSet(self)
+ h = handler.XmlHandler(rs, self)
+ xml.sax.parseString(body, h)
+ return rs.StorageClass
+ else:
+ raise self.connection.provider.storage_response_error(
+ response.status, response.reason, body)
+
+
+ # Method with same signature as boto.s3.bucket.Bucket.add_email_grant(),
+ # to allow polymorphic treatment at application layer.
+ def add_email_grant(self, permission, email_address,
+ recursive=False, headers=None):
+ """
+ Convenience method that provides a quick way to add an email grant
+ to a bucket. This method retrieves the current ACL, creates a new
+ grant based on the parameters passed in, adds that grant to the ACL
+ and then PUT's the new ACL back to GCS.
+
+ :type permission: string
+ :param permission: The permission being granted. Should be one of:
+ (READ, WRITE, FULL_CONTROL).
+
+ :type email_address: string
+ :param email_address: The email address associated with the GS
+ account your are granting the permission to.
+
+ :type recursive: bool
+ :param recursive: A boolean value to controls whether the call
+ will apply the grant to all keys within the bucket
+ or not. The default value is False. By passing a
+ True value, the call will iterate through all keys
+ in the bucket and apply the same grant to each key.
+ CAUTION: If you have a lot of keys, this could take
+ a long time!
+ """
+ if permission not in GSPermissions:
+ raise self.connection.provider.storage_permissions_error(
+ 'Unknown Permission: %s' % permission)
+ acl = self.get_acl(headers=headers)
+ acl.add_email_grant(permission, email_address)
+ self.set_acl(acl, headers=headers)
+ if recursive:
+ for key in self:
+ key.add_email_grant(permission, email_address, headers=headers)
+
+ # Method with same signature as boto.s3.bucket.Bucket.add_user_grant(),
+ # to allow polymorphic treatment at application layer.
+ def add_user_grant(self, permission, user_id, recursive=False,
+ headers=None):
+ """
+ Convenience method that provides a quick way to add a canonical user
+ grant to a bucket. This method retrieves the current ACL, creates a new
+ grant based on the parameters passed in, adds that grant to the ACL and
+ then PUTs the new ACL back to GCS.
+
+ :type permission: string
+ :param permission: The permission being granted. Should be one of:
+ (READ|WRITE|FULL_CONTROL)
+
+ :type user_id: string
+ :param user_id: The canonical user id associated with the GS account
+ you are granting the permission to.
+
+ :type recursive: bool
+ :param recursive: A boolean value to controls whether the call
+ will apply the grant to all keys within the bucket
+ or not. The default value is False. By passing a
+ True value, the call will iterate through all keys
+ in the bucket and apply the same grant to each key.
+ CAUTION: If you have a lot of keys, this could take
+ a long time!
+ """
+ if permission not in GSPermissions:
+ raise self.connection.provider.storage_permissions_error(
+ 'Unknown Permission: %s' % permission)
+ acl = self.get_acl(headers=headers)
+ acl.add_user_grant(permission, user_id)
+ self.set_acl(acl, headers=headers)
+ if recursive:
+ for key in self:
+ key.add_user_grant(permission, user_id, headers=headers)
+
+ def add_group_email_grant(self, permission, email_address, recursive=False,
+ headers=None):
+ """
+ Convenience method that provides a quick way to add an email group
+ grant to a bucket. This method retrieves the current ACL, creates a new
+ grant based on the parameters passed in, adds that grant to the ACL and
+ then PUT's the new ACL back to GCS.
+
+ :type permission: string
+ :param permission: The permission being granted. Should be one of:
+ READ|WRITE|FULL_CONTROL
+ See http://code.google.com/apis/storage/docs/developer-guide.html#authorization
+ for more details on permissions.
+
+ :type email_address: string
+ :param email_address: The email address associated with the Google
+ Group to which you are granting the permission.
+
+ :type recursive: bool
+ :param recursive: A boolean value to controls whether the call
+ will apply the grant to all keys within the bucket
+ or not. The default value is False. By passing a
+ True value, the call will iterate through all keys
+ in the bucket and apply the same grant to each key.
+ CAUTION: If you have a lot of keys, this could take
+ a long time!
+ """
+ if permission not in GSPermissions:
+ raise self.connection.provider.storage_permissions_error(
+ 'Unknown Permission: %s' % permission)
+ acl = self.get_acl(headers=headers)
+ acl.add_group_email_grant(permission, email_address)
+ self.set_acl(acl, headers=headers)
+ if recursive:
+ for key in self:
+ key.add_group_email_grant(permission, email_address,
+ headers=headers)
+
+ # Method with same input signature as boto.s3.bucket.Bucket.list_grants()
+ # (but returning different object type), to allow polymorphic treatment
+ # at application layer.
+ def list_grants(self, headers=None):
+ """Returns the ACL entries applied to this bucket.
+
+ :param dict headers: Additional headers to send with the request.
+ :rtype: list containing :class:`~.gs.acl.Entry` objects.
+ """
+ acl = self.get_acl(headers=headers)
+ return acl.entries
+
+ def disable_logging(self, headers=None):
+ """Disable logging on this bucket.
+
+ :param dict headers: Additional headers to send with the request.
+ """
+ xml_str = '<?xml version="1.0" encoding="UTF-8"?><Logging/>'
+ self.set_subresource('logging', xml_str, headers=headers)
+
+ def enable_logging(self, target_bucket, target_prefix=None, headers=None):
+ """Enable logging on a bucket.
+
+ :type target_bucket: bucket or string
+ :param target_bucket: The bucket to log to.
+
+ :type target_prefix: string
+ :param target_prefix: The prefix which should be prepended to the
+ generated log files written to the target_bucket.
+
+ :param dict headers: Additional headers to send with the request.
+ """
+ if isinstance(target_bucket, Bucket):
+ target_bucket = target_bucket.name
+ xml_str = '<?xml version="1.0" encoding="UTF-8"?><Logging>'
+ xml_str = (xml_str + '<LogBucket>%s</LogBucket>' % target_bucket)
+ if target_prefix:
+ xml_str = (xml_str +
+ '<LogObjectPrefix>%s</LogObjectPrefix>' % target_prefix)
+ xml_str = xml_str + '</Logging>'
+
+ self.set_subresource('logging', xml_str, headers=headers)
+
+ def configure_website(self, main_page_suffix=None, error_key=None,
+ headers=None):
+ """Configure this bucket to act as a website
+
+ :type main_page_suffix: str
+ :param main_page_suffix: Suffix that is appended to a request that is
+ for a "directory" on the website endpoint (e.g. if the suffix is
+ index.html and you make a request to samplebucket/images/ the data
+ that is returned will be for the object with the key name
+ images/index.html). The suffix must not be empty and must not
+ include a slash character. This parameter is optional and the
+ property is disabled if excluded.
+
+ :type error_key: str
+ :param error_key: The object key name to use when a 400 error occurs.
+ This parameter is optional and the property is disabled if excluded.
+
+ :param dict headers: Additional headers to send with the request.
+ """
+ if main_page_suffix:
+ main_page_frag = self.WebsiteMainPageFragment % main_page_suffix
+ else:
+ main_page_frag = ''
+
+ if error_key:
+ error_frag = self.WebsiteErrorFragment % error_key
+ else:
+ error_frag = ''
+
+ body = self.WebsiteBody % (main_page_frag, error_frag)
+ response = self.connection.make_request('PUT', self.name, data=body,
+ query_args='websiteConfig',
+ headers=headers)
+ body = response.read()
+ if response.status == 200:
+ return True
+ else:
+ raise self.connection.provider.storage_response_error(
+ response.status, response.reason, body)
+
+ def get_website_configuration(self, headers=None):
+ """Returns the current status of website configuration on the bucket.
+
+ :param dict headers: Additional headers to send with the request.
+
+ :rtype: dict
+ :returns: A dictionary containing a Python representation
+ of the XML response from GCS. The overall structure is:
+
+ * WebsiteConfiguration
+
+ * MainPageSuffix: suffix that is appended to request that
+ is for a "directory" on the website endpoint.
+ * NotFoundPage: name of an object to serve when site visitors
+ encounter a 404.
+ """
+ return self.get_website_configuration_xml(self, headers)[0]
+
+ def get_website_configuration_with_xml(self, headers=None):
+ """Returns the current status of website configuration on the bucket as
+ unparsed XML.
+
+ :param dict headers: Additional headers to send with the request.
+
+ :rtype: 2-Tuple
+ :returns: 2-tuple containing:
+
+ 1) A dictionary containing a Python representation of the XML
+ response from GCS. The overall structure is:
+
+ * WebsiteConfiguration
+
+ * MainPageSuffix: suffix that is appended to request that is for
+ a "directory" on the website endpoint.
+ * NotFoundPage: name of an object to serve when site visitors
+ encounter a 404
+
+ 2) Unparsed XML describing the bucket's website configuration.
+ """
+ response = self.connection.make_request('GET', self.name,
+ query_args='websiteConfig', headers=headers)
+ body = response.read()
+ boto.log.debug(body)
+
+ if response.status != 200:
+ raise self.connection.provider.storage_response_error(
+ response.status, response.reason, body)
+
+ e = boto.jsonresponse.Element()
+ h = boto.jsonresponse.XmlHandler(e, None)
+ h.parse(body)
+ return e, body
+
+ def delete_website_configuration(self, headers=None):
+ """Remove the website configuration from this bucket.
+
+ :param dict headers: Additional headers to send with the request.
+ """
+ self.configure_website(headers=headers)
+
+ def get_versioning_status(self, headers=None):
+ """Returns the current status of versioning configuration on the bucket.
+
+ :rtype: bool
+ """
+ response = self.connection.make_request('GET', self.name,
+ query_args='versioning',
+ headers=headers)
+ body = response.read()
+ boto.log.debug(body)
+ if response.status != 200:
+ raise self.connection.provider.storage_response_error(
+ response.status, response.reason, body)
+ resp_json = boto.jsonresponse.Element()
+ boto.jsonresponse.XmlHandler(resp_json, None).parse(body)
+ resp_json = resp_json['VersioningConfiguration']
+ return ('Status' in resp_json) and (resp_json['Status'] == 'Enabled')
+
+ def configure_versioning(self, enabled, headers=None):
+ """Configure versioning for this bucket.
+
+ :param bool enabled: If set to True, enables versioning on this bucket.
+ If set to False, disables versioning.
+
+ :param dict headers: Additional headers to send with the request.
+ """
+ if enabled == True:
+ req_body = self.VersioningBody % ('Enabled')
+ else:
+ req_body = self.VersioningBody % ('Suspended')
+ self.set_subresource('versioning', req_body, headers=headers)
« no previous file with comments | « third_party/gsutil/boto/boto/gs/acl.py ('k') | third_party/gsutil/boto/boto/gs/bucketlistresultset.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698