2525from gcloud .exceptions import NotFound
2626from gcloud .iterator import Iterator
2727from gcloud .storage ._helpers import _PropertyMixin
28- from gcloud .storage ._helpers import _require_connection
2928from gcloud .storage ._helpers import _scalar_property
3029from gcloud .storage .acl import BucketACL
3130from gcloud .storage .acl import DefaultObjectACL
@@ -45,17 +44,18 @@ class _BlobIterator(Iterator):
4544 :type extra_params: dict or None
4645 :param extra_params: Extra query string parameters for the API call.
4746
48- :type connection : :class:`gcloud.storage.connection.Connection `
49- :param connection: The connection to use when sending requests. Defaults
50- to the bucket's connection
47+ :type client : :class:`gcloud.storage.client.Client `
48+ :param client: Optional. The client to use for making connections.
49+ Defaults to the bucket's client.
5150 """
52- def __init__ (self , bucket , extra_params = None , connection = None ):
53- connection = _require_connection (connection )
51+ def __init__ (self , bucket , extra_params = None , client = None ):
52+ if client is None :
53+ client = bucket .client
5454 self .bucket = bucket
5555 self .prefixes = set ()
5656 self ._current_prefixes = None
5757 super (_BlobIterator , self ).__init__ (
58- connection = connection , path = bucket .path + '/o' ,
58+ connection = client . connection , path = bucket .path + '/o' ,
5959 extra_params = extra_params )
6060
6161 def get_items_from_response (self , response ):
@@ -76,6 +76,10 @@ def get_items_from_response(self, response):
7676class Bucket (_PropertyMixin ):
7777 """A class representing a Bucket on Cloud Storage.
7878
79+ :type client: :class:`gcloud.storage.client.Client`
80+ :param client: A client which holds credentials and project configuration
81+ for the bucket (which requires a project).
82+
7983 :type name: string
8084 :param name: The name of the bucket.
8185 """
@@ -87,60 +91,57 @@ class Bucket(_PropertyMixin):
8791 This is used in Bucket.delete() and Bucket.make_public().
8892 """
8993
90- def __init__ (self , name = None ):
94+ def __init__ (self , client , name = None ):
9195 super (Bucket , self ).__init__ (name = name )
96+ self ._client = client
9297 self ._acl = BucketACL (self )
9398 self ._default_object_acl = DefaultObjectACL (self )
9499
95100 def __repr__ (self ):
96101 return '<Bucket: %s>' % self .name
97102
98- @staticmethod
99- def _client_or_connection (client ):
100- """Temporary method to get a connection from a client.
101-
102- If the client is null, gets the connection from the environment.
103+ def _require_client (self , client ):
104+ """Check client or verify over-ride.
103105
104106 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
105- :param client: Optional. The client to use. If not passed, falls back
106- to default connection .
107+ :param client: the client to use. If not passed, falls back to the
108+ ``client`` stored on the current object .
107109
108- :rtype: :class:`gcloud.storage.connection.Connection `
109- :returns: The connection determined from the ``client`` or environment .
110+ :rtype: :class:`gcloud.storage.client.Client `
111+ :returns: The client passed in or the currently bound client .
110112 """
111113 if client is None :
112- return _require_connection ()
113- else :
114- return client .connection
114+ client = self .client
115+ return client
115116
116117 def exists (self , client = None ):
117118 """Determines whether or not this bucket exists.
118119
119120 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
120121 :param client: Optional. The client to use. If not passed, falls back
121- to default connection .
122+ to the ``client`` stored on the current bucket .
122123
123124 :rtype: boolean
124125 :returns: True if the bucket exists in Cloud Storage.
125126 """
126- connection = self ._client_or_connection (client )
127+ client = self ._require_client (client )
127128 try :
128129 # We only need the status code (200 or not) so we seek to
129130 # minimize the returned payload.
130131 query_params = {'fields' : 'name' }
131132 # We intentionally pass `_target_object=None` since fields=name
132133 # would limit the local properties.
133- connection .api_request (method = 'GET' , path = self .path ,
134- query_params = query_params ,
135- _target_object = None )
134+ client . connection .api_request (method = 'GET' , path = self .path ,
135+ query_params = query_params ,
136+ _target_object = None )
136137 # NOTE: This will not fail immediately in a batch. However, when
137138 # Batch.finish() is called, the resulting `NotFound` will be
138139 # raised.
139140 return True
140141 except NotFound :
141142 return False
142143
143- def create (self , project = None , connection = None ):
144+ def create (self , project = None , client = None ):
144145 """Creates current bucket.
145146
146147 If the bucket already exists, will raise
@@ -152,25 +153,24 @@ def create(self, project=None, connection=None):
152153 :param project: Optional. The project to use when creating bucket.
153154 If not provided, falls back to default.
154155
155- :type connection: :class:`gcloud.storage.connection.Connection` or
156- ``NoneType``
157- :param connection: Optional. The connection to use when sending
158- requests. If not provided, falls back to default.
156+ :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
157+ :param client: Optional. The client to use. If not passed, falls back
158+ to the ``client`` stored on the current bucket.
159159
160160 :rtype: :class:`gcloud.storage.bucket.Bucket`
161161 :returns: The newly created bucket.
162162 :raises: :class:`EnvironmentError` if the project is not given and
163163 can't be inferred.
164164 """
165- connection = _require_connection ( connection )
165+ client = self . _require_client ( client )
166166 if project is None :
167167 project = get_default_project ()
168168 if project is None :
169169 raise EnvironmentError ('Project could not be inferred '
170170 'from environment.' )
171171
172172 query_params = {'project' : project }
173- api_response = connection .api_request (
173+ api_response = client . connection .api_request (
174174 method = 'POST' , path = '/b' , query_params = query_params ,
175175 data = {'name' : self .name }, _target_object = self )
176176 self ._set_properties (api_response )
@@ -205,6 +205,11 @@ def path(self):
205205
206206 return self .path_helper (self .name )
207207
208+ @property
209+ def client (self ):
210+ """The client bound to this bucket."""
211+ return self ._client
212+
208213 def get_blob (self , blob_name , client = None ):
209214 """Get a blob object by name.
210215
@@ -223,15 +228,15 @@ def get_blob(self, blob_name, client=None):
223228
224229 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
225230 :param client: Optional. The client to use. If not passed, falls back
226- to default connection .
231+ to the ``client`` stored on the current bucket .
227232
228233 :rtype: :class:`gcloud.storage.blob.Blob` or None
229234 :returns: The blob object if it exists, otherwise None.
230235 """
231- connection = self ._client_or_connection (client )
236+ client = self ._require_client (client )
232237 blob = Blob (bucket = self , name = blob_name )
233238 try :
234- response = connection .api_request (
239+ response = client . connection .api_request (
235240 method = 'GET' , path = blob .path , _target_object = blob )
236241 # NOTE: We assume response.get('name') matches `blob_name`.
237242 blob ._set_properties (response )
@@ -244,7 +249,7 @@ def get_blob(self, blob_name, client=None):
244249
245250 def list_blobs (self , max_results = None , page_token = None , prefix = None ,
246251 delimiter = None , versions = None ,
247- projection = 'noAcl' , fields = None , connection = None ):
252+ projection = 'noAcl' , fields = None , client = None ):
248253 """Return an iterator used to find blobs in the bucket.
249254
250255 :type max_results: integer or ``NoneType``
@@ -276,10 +281,9 @@ def list_blobs(self, max_results=None, page_token=None, prefix=None,
276281 and the language of each blob returned:
277282 'items/contentLanguage,nextPageToken'
278283
279- :type connection: :class:`gcloud.storage.connection.Connection` or
280- ``NoneType``
281- :param connection: Optional. The connection to use when sending
282- requests. If not provided, falls back to default.
284+ :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
285+ :param client: Optional. The client to use. If not passed, falls back
286+ to the ``client`` stored on the current bucket.
283287
284288 :rtype: :class:`_BlobIterator`.
285289 :returns: An iterator of blobs.
@@ -304,7 +308,7 @@ def list_blobs(self, max_results=None, page_token=None, prefix=None,
304308 extra_params ['fields' ] = fields
305309
306310 result = self ._iterator_class (
307- self , extra_params = extra_params , connection = connection )
311+ self , extra_params = extra_params , client = client )
308312 # Page token must be handled specially since the base `Iterator`
309313 # class has it as a reserved property.
310314 if page_token is not None :
@@ -332,16 +336,16 @@ def delete(self, force=False, client=None):
332336
333337 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
334338 :param client: Optional. The client to use. If not passed, falls back
335- to default connection .
339+ to the ``client`` stored on the current bucket .
336340
337341 :raises: :class:`ValueError` if ``force`` is ``True`` and the bucket
338342 contains more than 256 objects / blobs.
339343 """
340- connection = self ._client_or_connection (client )
344+ client = self ._require_client (client )
341345 if force :
342346 blobs = list (self .list_blobs (
343347 max_results = self ._MAX_OBJECTS_FOR_ITERATION + 1 ,
344- connection = connection ))
348+ client = client ))
345349 if len (blobs ) > self ._MAX_OBJECTS_FOR_ITERATION :
346350 message = (
347351 'Refusing to delete bucket with more than '
@@ -358,8 +362,8 @@ def delete(self, force=False, client=None):
358362 # We intentionally pass `_target_object=None` since a DELETE
359363 # request has no response value (whether in a standard request or
360364 # in a batch request).
361- connection .api_request (method = 'DELETE' , path = self .path ,
362- _target_object = None )
365+ client . connection .api_request (method = 'DELETE' , path = self .path ,
366+ _target_object = None )
363367
364368 def delete_blob (self , blob_name , client = None ):
365369 """Deletes a blob from the current bucket.
@@ -386,21 +390,21 @@ def delete_blob(self, blob_name, client=None):
386390
387391 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
388392 :param client: Optional. The client to use. If not passed, falls back
389- to default connection .
393+ to the ``client`` stored on the current bucket .
390394
391395 :raises: :class:`gcloud.exceptions.NotFound` (to suppress
392396 the exception, call ``delete_blobs``, passing a no-op
393397 ``on_error`` callback, e.g.::
394398
395399 >>> bucket.delete_blobs([blob], on_error=lambda blob: None)
396400 """
397- connection = self ._client_or_connection (client )
401+ client = self ._require_client (client )
398402 blob_path = Blob .path_helper (self .path , blob_name )
399403 # We intentionally pass `_target_object=None` since a DELETE
400404 # request has no response value (whether in a standard request or
401405 # in a batch request).
402- connection .api_request (method = 'DELETE' , path = blob_path ,
403- _target_object = None )
406+ client . connection .api_request (method = 'DELETE' , path = blob_path ,
407+ _target_object = None )
404408
405409 def delete_blobs (self , blobs , on_error = None , client = None ):
406410 """Deletes a list of blobs from the current bucket.
@@ -417,7 +421,7 @@ def delete_blobs(self, blobs, on_error=None, client=None):
417421
418422 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
419423 :param client: Optional. The client to use. If not passed, falls back
420- to default connection .
424+ to the ``client`` stored on the current bucket .
421425
422426 :raises: :class:`gcloud.exceptions.NotFound` (if
423427 `on_error` is not passed).
@@ -450,18 +454,18 @@ def copy_blob(self, blob, destination_bucket, new_name=None,
450454
451455 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
452456 :param client: Optional. The client to use. If not passed, falls back
453- to default connection .
457+ to the ``client`` stored on the current bucket .
454458
455459 :rtype: :class:`gcloud.storage.blob.Blob`
456460 :returns: The new Blob.
457461 """
458- connection = self ._client_or_connection (client )
462+ client = self ._require_client (client )
459463 if new_name is None :
460464 new_name = blob .name
461465 new_blob = Blob (bucket = destination_bucket , name = new_name )
462466 api_path = blob .path + '/copyTo' + new_blob .path
463- copy_result = connection .api_request (method = 'POST' , path = api_path ,
464- _target_object = new_blob )
467+ copy_result = client . connection .api_request (
468+ method = 'POST' , path = api_path , _target_object = new_blob )
465469 new_blob ._set_properties (copy_result )
466470 return new_blob
467471
@@ -500,7 +504,7 @@ def upload_file(self, filename, blob_name=None, client=None):
500504
501505 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
502506 :param client: Optional. The client to use. If not passed, falls back
503- to default connection .
507+ to the ``client`` stored on the current bucket .
504508
505509 :rtype: :class:`Blob`
506510 :returns: The updated Blob object.
@@ -546,7 +550,7 @@ def upload_file_object(self, file_obj, blob_name=None, client=None):
546550
547551 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
548552 :param client: Optional. The client to use. If not passed, falls back
549- to default connection .
553+ to the ``client`` stored on the current bucket .
550554
551555 :rtype: :class:`Blob`
552556 :returns: The updated Blob object.
@@ -847,10 +851,8 @@ def make_public(self, recursive=False, future=False, client=None):
847851
848852 :type client: :class:`gcloud.storage.client.Client` or ``NoneType``
849853 :param client: Optional. The client to use. If not passed, falls back
850- to default connection .
854+ to the ``client`` stored on the current bucket .
851855 """
852- connection = self ._client_or_connection (client )
853-
854856 self .acl .all ().grant_read ()
855857 self .acl .save (client = client )
856858
@@ -865,7 +867,7 @@ def make_public(self, recursive=False, future=False, client=None):
865867 blobs = list (self .list_blobs (
866868 projection = 'full' ,
867869 max_results = self ._MAX_OBJECTS_FOR_ITERATION + 1 ,
868- connection = connection ))
870+ client = client ))
869871 if len (blobs ) > self ._MAX_OBJECTS_FOR_ITERATION :
870872 message = (
871873 'Refusing to make public recursively with more than '
0 commit comments