Skip to content

Commit 54bf64e

Browse files
committed
Merge pull request #987 from dhermes/replace-connection-in-bucket
Replace connection in bucket constructor.
2 parents c11d9b5 + 017346a commit 54bf64e

File tree

7 files changed

+185
-198
lines changed

7 files changed

+185
-198
lines changed

gcloud/storage/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def set_default_bucket(bucket=None):
7878
bucket_name = os.getenv(_BUCKET_ENV_VAR_NAME)
7979

8080
if bucket_name is not None:
81-
bucket = Bucket(bucket_name)
81+
bucket = Bucket(None, name=bucket_name)
8282

8383
if bucket is not None:
8484
_implicit_environ._DEFAULTS.bucket = bucket

gcloud/storage/batch.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
from gcloud._helpers import _LocalStack
3030
from gcloud.exceptions import make_exception
31-
from gcloud.storage import _implicit_environ
3231
from gcloud.storage.connection import Connection
3332

3433

@@ -130,17 +129,14 @@ def __setitem__(self, key, value):
130129
class Batch(Connection):
131130
"""Proxy an underlying connection, batching up change operations.
132131
133-
:type connection: :class:`gcloud.storage.connection.Connection`
134-
:param connection: the connection for which the batch proxies.
132+
:type client: :class:`gcloud.storage.client.Client`
133+
:param client: The client to use for making connections.
135134
"""
136135
_MAX_BATCH_SIZE = 1000
137136

138-
def __init__(self, connection=None):
139-
if connection is None:
140-
connection = _implicit_environ.get_default_connection()
141-
137+
def __init__(self, client):
142138
super(Batch, self).__init__()
143-
self._connection = connection
139+
self._client = client
144140
self._requests = []
145141
self._target_objects = []
146142

@@ -248,7 +244,7 @@ def finish(self):
248244

249245
url = '%s/batch' % self.API_BASE_URL
250246

251-
response, content = self._connection._make_request(
247+
response, content = self._client.connection._make_request(
252248
'POST', url, data=body, headers=headers)
253249
responses = list(_unpack_batch_response(response, content))
254250
self._finish_futures(responses)

gcloud/storage/bucket.py

Lines changed: 63 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
from gcloud.exceptions import NotFound
2626
from gcloud.iterator import Iterator
2727
from gcloud.storage._helpers import _PropertyMixin
28-
from gcloud.storage._helpers import _require_connection
2928
from gcloud.storage._helpers import _scalar_property
3029
from gcloud.storage.acl import BucketACL
3130
from 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):
7676
class 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

Comments
 (0)