diff env/lib/python3.7/site-packages/boto/gs/bucket.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
line wrap: on
line diff
--- a/env/lib/python3.7/site-packages/boto/gs/bucket.py	Thu May 14 16:47:39 2020 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1134 +0,0 @@
-# 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 re
-import urllib
-import xml.sax
-
-import boto
-from boto import handler
-from boto.resultset import ResultSet
-from boto.exception import GSResponseError
-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.encryptionconfig import EncryptionConfig
-from boto.gs.lifecycle import LifecycleConfig
-from boto.gs.key import Key as GSKey
-from boto.s3.acl import Policy
-from boto.s3.bucket import Bucket as S3Bucket
-from boto.utils import get_utf8_value
-from boto.compat import six
-
-# constants for http query args
-DEF_OBJ_ACL = 'defaultObjectAcl'
-STANDARD_ACL = 'acl'
-CORS_ARG = 'cors'
-ENCRYPTION_CONFIG_ARG = 'encryptionConfig'
-LIFECYCLE_ARG = 'lifecycle'
-STORAGE_CLASS_ARG='storageClass'
-ERROR_DETAILS_REGEX = re.compile(r'<Details>(?P<details>.*)</Details>')
-
-class Bucket(S3Bucket):
-    """Represents a Google Cloud Storage bucket."""
-
-    BillingBody = ('<?xml version="1.0" encoding="UTF-8"?>\n'
-                   '<BillingConfiguration>'
-                   '<RequesterPays>%s</RequesterPays>'
-                   '</BillingConfiguration>')
-    EncryptionConfigBody = (
-        '<?xml version="1.0" encoding="UTF-8"?>\n'
-        '<EncryptionConfiguration>%s</EncryptionConfiguration>')
-    EncryptionConfigDefaultKeyNameFragment = (
-        '<DefaultKmsKeyName>%s</DefaultKmsKeyName>')
-    StorageClassBody = ('<?xml version="1.0" encoding="UTF-8"?>\n'
-                        '<StorageClass>%s</StorageClass>')
-    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 six.iteritems(response_headers):
-                query_args_l.append('%s=%s' % (rk, urllib.quote(rv)))
-        try:
-            key, resp = self._get_key_internal(key_name, headers,
-                                               query_args_l=query_args_l)
-        except GSResponseError as e:
-            if e.status == 403 and 'Forbidden' in e.reason:
-                # If we failed getting an object, let the user know which object
-                # failed rather than just returning a generic 403.
-                e.reason = ("Access denied to 'gs://%s/%s'." %
-                            (self.name, key_name))
-            raise
-        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 validate_get_all_versions_params(self, params):
-        """
-        See documentation in boto/s3/bucket.py.
-        """
-        self.validate_kwarg_names(params,
-                                  ['version_id_marker', 'delimiter', 'marker',
-                                   'generation_marker', 'prefix', 'max_keys'])
-
-    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:
-            if response.status == 403:
-                match = ERROR_DETAILS_REGEX.search(body)
-                details = match.group('details') if match else None
-                if details:
-                    details = (('<Details>%s. Note that Full Control access'
-                                ' is required to access ACLs.</Details>') %
-                               details)
-                    body = re.sub(ERROR_DETAILS_REGEX, details, body)
-            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
-
-        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 metageneration 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', get_utf8_value(self.name), get_utf8_value(key_name),
-            data=get_utf8_value(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.
-        """
-        response = self.connection.make_request(
-            'PUT', get_utf8_value(self.name), data=get_utf8_value(cors),
-            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, headers=None):
-        """
-        Returns the StorageClass for the bucket.
-
-        :rtype: str
-        :return: The StorageClass for the bucket.
-        """
-        response = self.connection.make_request('GET', self.name,
-                                                query_args=STORAGE_CLASS_ARG,
-                                                headers=headers)
-        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)
-
-    def set_storage_class(self, storage_class, headers=None):
-        """
-        Sets a bucket's storage class.
-
-        :param str storage_class: A string containing the storage class.
-        :param dict headers: Additional headers to send with the request.
-        """
-        req_body = self.StorageClassBody % (get_utf8_value(storage_class))
-        self.set_subresource(STORAGE_CLASS_ARG, req_body, headers=headers)
-
-    # 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 get_logging_config_with_xml(self, headers=None):
-        """Returns the current status of logging 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 the parsed XML response from GCS. The
-              overall structure is:
-
-              * Logging
-
-                * LogObjectPrefix: Prefix that is prepended to log objects.
-                * LogBucket: Target bucket for log objects.
-
-            2) Unparsed XML describing the bucket's logging configuration.
-        """
-        response = self.connection.make_request('GET', self.name,
-                                                query_args='logging',
-                                                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 get_logging_config(self, headers=None):
-        """Returns the current status of logging configuration on the bucket.
-
-        :param dict headers: Additional headers to send with the request.
-
-        :rtype: dict
-        :returns: A dictionary containing the parsed XML response from GCS. The
-            overall structure is:
-
-            * Logging
-
-              * LogObjectPrefix: Prefix that is prepended to log objects.
-              * LogBucket: Target bucket for log objects.
-        """
-        return self.get_logging_config_with_xml(headers)[0]
-
-    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', get_utf8_value(self.name), data=get_utf8_value(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 the parsed 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_with_xml(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 the parsed 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)
-
-    def get_lifecycle_config(self, headers=None):
-        """
-        Returns the current lifecycle configuration on the bucket.
-
-        :rtype: :class:`boto.gs.lifecycle.LifecycleConfig`
-        :returns: A LifecycleConfig object that describes all current
-            lifecycle rules in effect for the bucket.
-        """
-        response = self.connection.make_request('GET', self.name,
-                query_args=LIFECYCLE_ARG, headers=headers)
-        body = response.read()
-        boto.log.debug(body)
-        if response.status == 200:
-            lifecycle_config = LifecycleConfig()
-            h = handler.XmlHandler(lifecycle_config, self)
-            xml.sax.parseString(body, h)
-            return lifecycle_config
-        else:
-            raise self.connection.provider.storage_response_error(
-                response.status, response.reason, body)
-
-    def configure_lifecycle(self, lifecycle_config, headers=None):
-        """
-        Configure lifecycle for this bucket.
-
-        :type lifecycle_config: :class:`boto.gs.lifecycle.LifecycleConfig`
-        :param lifecycle_config: The lifecycle configuration you want
-            to configure for this bucket.
-        """
-        xml = lifecycle_config.to_xml()
-        response = self.connection.make_request(
-            'PUT', get_utf8_value(self.name), data=get_utf8_value(xml),
-            query_args=LIFECYCLE_ARG, 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_billing_config(self, headers=None):
-        """Returns the current status of billing configuration on the bucket.
-
-        :param dict headers: Additional headers to send with the request.
-
-        :rtype: dict
-        :returns: A dictionary containing the parsed XML response from GCS. The
-            overall structure is:
-
-            * BillingConfiguration
-
-              * RequesterPays: Enabled/Disabled.
-        """
-        return self.get_billing_configuration_with_xml(headers)[0]
-
-    def get_billing_configuration_with_xml(self, headers=None):
-        """Returns the current status of billing 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 the parsed XML response from GCS. The
-              overall structure is:
-
-              * BillingConfiguration
-
-                * RequesterPays: Enabled/Disabled.
-
-            2) Unparsed XML describing the bucket's website configuration.
-        """
-        response = self.connection.make_request('GET', self.name,
-                                                query_args='billing',
-                                                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 configure_billing(self, requester_pays=False, headers=None):
-        """Configure billing for this bucket.
-
-        :param bool requester_pays: If set to True, enables requester pays on
-            this bucket. If set to False, disables requester pays.
-
-        :param dict headers: Additional headers to send with the request.
-        """
-        if requester_pays == True:
-            req_body = self.BillingBody % ('Enabled')
-        else:
-            req_body = self.BillingBody % ('Disabled')
-        self.set_subresource('billing', req_body, headers=headers)
-
-    def get_encryption_config(self, headers=None):
-        """Returns a bucket's EncryptionConfig.
-
-        :param dict headers: Additional headers to send with the request.
-        :rtype: :class:`~.encryption_config.EncryptionConfig`
-        """
-        response = self.connection.make_request(
-            'GET', self.name, query_args=ENCRYPTION_CONFIG_ARG, headers=headers)
-        body = response.read()
-        if response.status == 200:
-            # Success - parse XML and return EncryptionConfig object.
-            encryption_config = EncryptionConfig()
-            h = handler.XmlHandler(encryption_config, self)
-            xml.sax.parseString(body, h)
-            return encryption_config
-        else:
-            raise self.connection.provider.storage_response_error(
-                response.status, response.reason, body)
-
-    def _construct_encryption_config_xml(self, default_kms_key_name=None):
-        """Creates an XML document for setting a bucket's EncryptionConfig.
-
-        This method is internal as it's only here for testing purposes. As
-        managing Cloud KMS resources for testing is complex, we settle for
-        testing that we're creating correctly-formed XML for setting a bucket's
-        encryption configuration.
-
-        :param str default_kms_key_name: A string containing a fully-qualified
-            Cloud KMS key name.
-        :rtype: str
-        """
-        if default_kms_key_name:
-            default_kms_key_name_frag = (
-                self.EncryptionConfigDefaultKeyNameFragment %
-                default_kms_key_name)
-        else:
-            default_kms_key_name_frag = ''
-
-        return self.EncryptionConfigBody % default_kms_key_name_frag
-
-
-    def set_encryption_config(self, default_kms_key_name=None, headers=None):
-        """Sets a bucket's EncryptionConfig XML document.
-
-        :param str default_kms_key_name: A string containing a fully-qualified
-            Cloud KMS key name.
-        :param dict headers: Additional headers to send with the request.
-        """
-        body = self._construct_encryption_config_xml(
-            default_kms_key_name=default_kms_key_name)
-        response = self.connection.make_request(
-            'PUT', get_utf8_value(self.name), data=get_utf8_value(body),
-            query_args=ENCRYPTION_CONFIG_ARG, headers=headers)
-        body = response.read()
-        if response.status != 200:
-            raise self.connection.provider.storage_response_error(
-                response.status, response.reason, body)