1# Copyright 2015 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Client for interacting with the Google Cloud Storage API."""
16
17import base64
18import binascii
19import collections
20import datetime
21import functools
22import json
23import warnings
24import google.api_core.client_options
25
26from google.auth.credentials import AnonymousCredentials
27
28from google.api_core import page_iterator
29from google.cloud._helpers import _LocalStack
30from google.cloud.client import ClientWithProject
31from google.cloud.exceptions import NotFound
32
33from google.cloud.storage._helpers import _add_generation_match_parameters
34from google.cloud.storage._helpers import _bucket_bound_hostname_url
35from google.cloud.storage._helpers import _get_api_endpoint_override
36from google.cloud.storage._helpers import _get_environ_project
37from google.cloud.storage._helpers import _get_storage_emulator_override
38from google.cloud.storage._helpers import _use_client_cert
39from google.cloud.storage._helpers import _virtual_hosted_style_base_url
40from google.cloud.storage._helpers import _DEFAULT_UNIVERSE_DOMAIN
41from google.cloud.storage._helpers import _DEFAULT_SCHEME
42from google.cloud.storage._helpers import _STORAGE_HOST_TEMPLATE
43from google.cloud.storage._helpers import _NOW
44from google.cloud.storage._helpers import _UTC
45from google.cloud.storage._opentelemetry_tracing import create_trace_span
46
47from google.cloud.storage._http import Connection
48from google.cloud.storage._signing import (
49 get_expiration_seconds_v4,
50 get_v4_now_dtstamps,
51 ensure_signed_credentials,
52 _sign_message,
53)
54from google.cloud.storage.batch import Batch
55from google.cloud.storage.bucket import Bucket, _item_to_blob, _blobs_page_start
56from google.cloud.storage.blob import Blob
57from google.cloud.storage.hmac_key import HMACKeyMetadata
58from google.cloud.storage.acl import BucketACL
59from google.cloud.storage.acl import DefaultObjectACL
60from google.cloud.storage.constants import _DEFAULT_TIMEOUT
61from google.cloud.storage.retry import DEFAULT_RETRY
62
63
64_marker = object()
65
66
67class Client(ClientWithProject):
68 """Client to bundle configuration needed for API requests.
69
70 :type project: str or None
71 :param project: the project which the client acts on behalf of. Will be
72 passed when creating a topic. If not passed,
73 falls back to the default inferred from the environment.
74
75 :type credentials: :class:`~google.auth.credentials.Credentials`
76 :param credentials: (Optional) The OAuth2 Credentials to use for this
77 client. If not passed (and if no ``_http`` object is
78 passed), falls back to the default inferred from the
79 environment.
80
81 :type _http: :class:`~requests.Session`
82 :param _http: (Optional) HTTP object to make requests. Can be any object
83 that defines ``request()`` with the same interface as
84 :meth:`requests.Session.request`. If not passed, an
85 ``_http`` object is created that is bound to the
86 ``credentials`` for the current object.
87 This parameter should be considered private, and could
88 change in the future.
89
90 :type client_info: :class:`~google.api_core.client_info.ClientInfo`
91 :param client_info:
92 The client info used to send a user-agent string along with API
93 requests. If ``None``, then default info will be used. Generally,
94 you only need to set this if you're developing your own library
95 or partner tool.
96
97 :type client_options: :class:`~google.api_core.client_options.ClientOptions` or :class:`dict`
98 :param client_options: (Optional) Client options used to set user options on the client.
99 A non-default universe domain or api endpoint should be set through client_options.
100
101 :type use_auth_w_custom_endpoint: bool
102 :param use_auth_w_custom_endpoint:
103 (Optional) Whether authentication is required under custom endpoints.
104 If false, uses AnonymousCredentials and bypasses authentication.
105 Defaults to True. Note this is only used when a custom endpoint is set in conjunction.
106
107 :type extra_headers: dict
108 :param extra_headers:
109 (Optional) Custom headers to be sent with the requests attached to the client.
110 For example, you can add custom audit logging headers.
111
112 :type api_key: string
113 :param api_key:
114 (Optional) An API key. Mutually exclusive with any other credentials.
115 This parameter is an alias for setting `client_options.api_key` and
116 will supercede any api key set in the `client_options` parameter.
117 """
118
119 SCOPE = (
120 "https://www.googleapis.com/auth/devstorage.full_control",
121 "https://www.googleapis.com/auth/devstorage.read_only",
122 "https://www.googleapis.com/auth/devstorage.read_write",
123 )
124 """The scopes required for authenticating as a Cloud Storage consumer."""
125
126 def __init__(
127 self,
128 project=_marker,
129 credentials=None,
130 _http=None,
131 client_info=None,
132 client_options=None,
133 use_auth_w_custom_endpoint=True,
134 extra_headers={},
135 *,
136 api_key=None,
137 ):
138 self._base_connection = None
139
140 if project is None:
141 no_project = True
142 project = "<none>"
143 else:
144 no_project = False
145
146 if project is _marker:
147 project = None
148
149 # Save the initial value of constructor arguments before they
150 # are passed along, for use in __reduce__ defined elsewhere.
151 self._initial_client_info = client_info
152 self._initial_client_options = client_options
153 self._extra_headers = extra_headers
154
155 connection_kw_args = {"client_info": client_info}
156
157 # api_key should set client_options.api_key. Set it here whether
158 # client_options was specified as a dict, as a ClientOptions object, or
159 # None.
160 if api_key:
161 if client_options and not isinstance(client_options, dict):
162 client_options.api_key = api_key
163 else:
164 if not client_options:
165 client_options = {}
166 client_options["api_key"] = api_key
167
168 if client_options:
169 if isinstance(client_options, dict):
170 client_options = google.api_core.client_options.from_dict(
171 client_options
172 )
173
174 if client_options and client_options.universe_domain:
175 self._universe_domain = client_options.universe_domain
176 else:
177 self._universe_domain = None
178
179 storage_emulator_override = _get_storage_emulator_override()
180 api_endpoint_override = _get_api_endpoint_override()
181
182 # Determine the api endpoint. The rules are as follows:
183
184 # 1. If the `api_endpoint` is set in `client_options`, use that as the
185 # endpoint.
186 if client_options and client_options.api_endpoint:
187 api_endpoint = client_options.api_endpoint
188
189 # 2. Elif the "STORAGE_EMULATOR_HOST" env var is set, then use that as the
190 # endpoint.
191 elif storage_emulator_override:
192 api_endpoint = storage_emulator_override
193
194 # 3. Elif the "API_ENDPOINT_OVERRIDE" env var is set, then use that as the
195 # endpoint.
196 elif api_endpoint_override:
197 api_endpoint = api_endpoint_override
198
199 # 4. Elif the `universe_domain` is set in `client_options`,
200 # create the endpoint using that as the default.
201 #
202 # Mutual TLS is not compatible with a non-default universe domain
203 # at this time. If such settings are enabled along with the
204 # "GOOGLE_API_USE_CLIENT_CERTIFICATE" env variable, a ValueError will
205 # be raised.
206
207 elif self._universe_domain:
208 # The final decision of whether to use mTLS takes place in
209 # google-auth-library-python. We peek at the environment variable
210 # here only to issue an exception in case of a conflict.
211 if _use_client_cert():
212 raise ValueError(
213 'The "GOOGLE_API_USE_CLIENT_CERTIFICATE" env variable is '
214 'set to "true" and a non-default universe domain is '
215 "configured. mTLS is not supported in any universe other than"
216 "googleapis.com."
217 )
218 api_endpoint = _DEFAULT_SCHEME + _STORAGE_HOST_TEMPLATE.format(
219 universe_domain=self._universe_domain
220 )
221
222 # 5. Else, use the default, which is to use the default
223 # universe domain of "googleapis.com" and create the endpoint
224 # "storage.googleapis.com" from that.
225 else:
226 api_endpoint = None
227
228 connection_kw_args["api_endpoint"] = api_endpoint
229
230 self._is_emulator_set = True if storage_emulator_override else False
231
232 # If a custom endpoint is set, the client checks for credentials
233 # or finds the default credentials based on the current environment.
234 # Authentication may be bypassed under certain conditions:
235 # (1) STORAGE_EMULATOR_HOST is set (for backwards compatibility), OR
236 # (2) use_auth_w_custom_endpoint is set to False.
237 if connection_kw_args["api_endpoint"] is not None:
238 if self._is_emulator_set or not use_auth_w_custom_endpoint:
239 if credentials is None:
240 credentials = AnonymousCredentials()
241 if project is None:
242 project = _get_environ_project()
243 if project is None:
244 no_project = True
245 project = "<none>"
246
247 super(Client, self).__init__(
248 project=project,
249 credentials=credentials,
250 client_options=client_options,
251 _http=_http,
252 )
253
254 # Validate that the universe domain of the credentials matches the
255 # universe domain of the client.
256 if self._credentials.universe_domain != self.universe_domain:
257 raise ValueError(
258 "The configured universe domain ({client_ud}) does not match "
259 "the universe domain found in the credentials ({cred_ud}). If "
260 "you haven't configured the universe domain explicitly, "
261 "`googleapis.com` is the default.".format(
262 client_ud=self.universe_domain,
263 cred_ud=self._credentials.universe_domain,
264 )
265 )
266
267 if no_project:
268 self.project = None
269
270 # Pass extra_headers to Connection
271 connection = Connection(self, **connection_kw_args)
272 connection.extra_headers = extra_headers
273 self._connection = connection
274 self._batch_stack = _LocalStack()
275
276 @classmethod
277 def create_anonymous_client(cls):
278 """Factory: return client with anonymous credentials.
279
280 .. note::
281
282 Such a client has only limited access to "public" buckets:
283 listing their contents and downloading their blobs.
284
285 :rtype: :class:`google.cloud.storage.client.Client`
286 :returns: Instance w/ anonymous credentials and no project.
287 """
288 client = cls(project="<none>", credentials=AnonymousCredentials())
289 client.project = None
290 return client
291
292 @property
293 def universe_domain(self):
294 return self._universe_domain or _DEFAULT_UNIVERSE_DOMAIN
295
296 @property
297 def api_endpoint(self):
298 return self._connection.API_BASE_URL
299
300 @property
301 def _connection(self):
302 """Get connection or batch on the client.
303
304 :rtype: :class:`google.cloud.storage._http.Connection`
305 :returns: The connection set on the client, or the batch
306 if one is set.
307 """
308 if self.current_batch is not None:
309 return self.current_batch
310 else:
311 return self._base_connection
312
313 @_connection.setter
314 def _connection(self, value):
315 """Set connection on the client.
316
317 Intended to be used by constructor (since the base class calls)
318 self._connection = connection
319 Will raise if the connection is set more than once.
320
321 :type value: :class:`google.cloud.storage._http.Connection`
322 :param value: The connection set on the client.
323
324 :raises: :class:`ValueError` if connection has already been set.
325 """
326 if self._base_connection is not None:
327 raise ValueError("Connection already set on client")
328 self._base_connection = value
329
330 def _push_batch(self, batch):
331 """Push a batch onto our stack.
332
333 "Protected", intended for use by batch context mgrs.
334
335 :type batch: :class:`google.cloud.storage.batch.Batch`
336 :param batch: newly-active batch
337 """
338 self._batch_stack.push(batch)
339
340 def _pop_batch(self):
341 """Pop a batch from our stack.
342
343 "Protected", intended for use by batch context mgrs.
344
345 :raises: IndexError if the stack is empty.
346 :rtype: :class:`google.cloud.storage.batch.Batch`
347 :returns: the top-most batch/transaction, after removing it.
348 """
349 return self._batch_stack.pop()
350
351 @property
352 def current_batch(self):
353 """Currently-active batch.
354
355 :rtype: :class:`google.cloud.storage.batch.Batch` or ``NoneType`` (if
356 no batch is active).
357 :returns: The batch at the top of the batch stack.
358 """
359 return self._batch_stack.top
360
361 def get_service_account_email(
362 self, project=None, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY
363 ):
364 """Get the email address of the project's GCS service account
365
366 :type project: str
367 :param project:
368 (Optional) Project ID to use for retreiving GCS service account
369 email address. Defaults to the client's project.
370 :type timeout: float or tuple
371 :param timeout:
372 (Optional) The amount of time, in seconds, to wait
373 for the server response. See: :ref:`configuring_timeouts`
374
375 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
376 :param retry:
377 (Optional) How to retry the RPC. See: :ref:`configuring_retries`
378
379 :rtype: str
380 :returns: service account email address
381 """
382 with create_trace_span(name="Storage.Client.getServiceAccountEmail"):
383 if project is None:
384 project = self.project
385
386 path = f"/projects/{project}/serviceAccount"
387 api_response = self._get_resource(path, timeout=timeout, retry=retry)
388 return api_response["email_address"]
389
390 def bucket(self, bucket_name, user_project=None, generation=None):
391 """Factory constructor for bucket object.
392
393 .. note::
394 This will not make an HTTP request; it simply instantiates
395 a bucket object owned by this client.
396
397 :type bucket_name: str
398 :param bucket_name: The name of the bucket to be instantiated.
399
400 :type user_project: str
401 :param user_project: (Optional) The project ID to be billed for API
402 requests made via the bucket.
403
404 :type generation: int
405 :param generation: (Optional) If present, selects a specific revision of
406 this bucket.
407
408 :rtype: :class:`google.cloud.storage.bucket.Bucket`
409 :returns: The bucket object created.
410 """
411 return Bucket(
412 client=self,
413 name=bucket_name,
414 user_project=user_project,
415 generation=generation,
416 )
417
418 def batch(self, raise_exception=True):
419 """Factory constructor for batch object.
420
421 .. note::
422 This will not make an HTTP request; it simply instantiates
423 a batch object owned by this client.
424
425 :type raise_exception: bool
426 :param raise_exception:
427 (Optional) Defaults to True. If True, instead of adding exceptions
428 to the list of return responses, the final exception will be raised.
429 Note that exceptions are unwrapped after all operations are complete
430 in success or failure, and only the last exception is raised.
431
432 :rtype: :class:`google.cloud.storage.batch.Batch`
433 :returns: The batch object created.
434 """
435 return Batch(client=self, raise_exception=raise_exception)
436
437 def _get_resource(
438 self,
439 path,
440 query_params=None,
441 headers=None,
442 timeout=_DEFAULT_TIMEOUT,
443 retry=DEFAULT_RETRY,
444 _target_object=None,
445 ):
446 """Helper for bucket / blob methods making API 'GET' calls.
447
448 Args:
449 path str:
450 The path of the resource to fetch.
451
452 query_params Optional[dict]:
453 HTTP query parameters to be passed
454
455 headers Optional[dict]:
456 HTTP headers to be passed
457
458 timeout (Optional[Union[float, Tuple[float, float]]]):
459 The amount of time, in seconds, to wait for the server response.
460
461 Can also be passed as a tuple (connect_timeout, read_timeout).
462 See :meth:`requests.Session.request` documentation for details.
463
464 retry (Optional[Union[google.api_core.retry.Retry, google.cloud.storage.retry.ConditionalRetryPolicy]]):
465 How to retry the RPC. A None value will disable retries.
466 A google.api_core.retry.Retry value will enable retries, and the object will
467 define retriable response codes and errors and configure backoff and timeout options.
468
469 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a Retry object and
470 activates it only if certain conditions are met. This class exists to provide safe defaults
471 for RPC calls that are not technically safe to retry normally (due to potential data
472 duplication or other side-effects) but become safe to retry if a condition such as
473 if_metageneration_match is set.
474
475 See the retry.py source code and docstrings in this package (google.cloud.storage.retry) for
476 information on retry types and how to configure them.
477
478 _target_object (Union[ \
479 :class:`~google.cloud.storage.bucket.Bucket`, \
480 :class:`~google.cloud.storage.bucket.blob`, \
481 ]):
482 Object to which future data is to be applied -- only relevant
483 in the context of a batch.
484
485 Returns:
486 dict
487 The JSON resource fetched
488
489 Raises:
490 google.cloud.exceptions.NotFound
491 If the bucket is not found.
492 """
493 return self._connection.api_request(
494 method="GET",
495 path=path,
496 query_params=query_params,
497 headers=headers,
498 timeout=timeout,
499 retry=retry,
500 _target_object=_target_object,
501 )
502
503 def _list_resource(
504 self,
505 path,
506 item_to_value,
507 page_token=None,
508 max_results=None,
509 extra_params=None,
510 page_start=page_iterator._do_nothing_page_start,
511 page_size=None,
512 timeout=_DEFAULT_TIMEOUT,
513 retry=DEFAULT_RETRY,
514 ):
515 kwargs = {
516 "method": "GET",
517 "path": path,
518 "timeout": timeout,
519 }
520 with create_trace_span(
521 name="Storage.Client._list_resource_returns_iterator",
522 client=self,
523 api_request=kwargs,
524 retry=retry,
525 ):
526 api_request = functools.partial(
527 self._connection.api_request, timeout=timeout, retry=retry
528 )
529 return page_iterator.HTTPIterator(
530 client=self,
531 api_request=api_request,
532 path=path,
533 item_to_value=item_to_value,
534 page_token=page_token,
535 max_results=max_results,
536 extra_params=extra_params,
537 page_start=page_start,
538 page_size=page_size,
539 )
540
541 def _patch_resource(
542 self,
543 path,
544 data,
545 query_params=None,
546 headers=None,
547 timeout=_DEFAULT_TIMEOUT,
548 retry=None,
549 _target_object=None,
550 ):
551 """Helper for bucket / blob methods making API 'PATCH' calls.
552
553 Args:
554 path str:
555 The path of the resource to fetch.
556
557 data dict:
558 The data to be patched.
559
560 query_params Optional[dict]:
561 HTTP query parameters to be passed
562
563 headers Optional[dict]:
564 HTTP headers to be passed
565
566 timeout (Optional[Union[float, Tuple[float, float]]]):
567 The amount of time, in seconds, to wait for the server response.
568
569 Can also be passed as a tuple (connect_timeout, read_timeout).
570 See :meth:`requests.Session.request` documentation for details.
571
572 retry (Optional[Union[google.api_core.retry.Retry, google.cloud.storage.retry.ConditionalRetryPolicy]]):
573 How to retry the RPC. A None value will disable retries.
574 A google.api_core.retry.Retry value will enable retries, and the object will
575 define retriable response codes and errors and configure backoff and timeout options.
576
577 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a Retry object and
578 activates it only if certain conditions are met. This class exists to provide safe defaults
579 for RPC calls that are not technically safe to retry normally (due to potential data
580 duplication or other side-effects) but become safe to retry if a condition such as
581 if_metageneration_match is set.
582
583 See the retry.py source code and docstrings in this package (google.cloud.storage.retry) for
584 information on retry types and how to configure them.
585
586 _target_object (Union[ \
587 :class:`~google.cloud.storage.bucket.Bucket`, \
588 :class:`~google.cloud.storage.bucket.blob`, \
589 ]):
590 Object to which future data is to be applied -- only relevant
591 in the context of a batch.
592
593 Returns:
594 dict
595 The JSON resource fetched
596
597 Raises:
598 google.cloud.exceptions.NotFound
599 If the bucket is not found.
600 """
601 return self._connection.api_request(
602 method="PATCH",
603 path=path,
604 data=data,
605 query_params=query_params,
606 headers=headers,
607 timeout=timeout,
608 retry=retry,
609 _target_object=_target_object,
610 )
611
612 def _put_resource(
613 self,
614 path,
615 data,
616 query_params=None,
617 headers=None,
618 timeout=_DEFAULT_TIMEOUT,
619 retry=None,
620 _target_object=None,
621 ):
622 """Helper for bucket / blob methods making API 'PUT' calls.
623
624 Args:
625 path str:
626 The path of the resource to fetch.
627
628 data dict:
629 The data to be patched.
630
631 query_params Optional[dict]:
632 HTTP query parameters to be passed
633
634 headers Optional[dict]:
635 HTTP headers to be passed
636
637 timeout (Optional[Union[float, Tuple[float, float]]]):
638 The amount of time, in seconds, to wait for the server response.
639
640 Can also be passed as a tuple (connect_timeout, read_timeout).
641 See :meth:`requests.Session.request` documentation for details.
642
643 retry (Optional[Union[google.api_core.retry.Retry, google.cloud.storage.retry.ConditionalRetryPolicy]]):
644 How to retry the RPC. A None value will disable retries.
645 A google.api_core.retry.Retry value will enable retries, and the object will
646 define retriable response codes and errors and configure backoff and timeout options.
647
648 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a Retry object and
649 activates it only if certain conditions are met. This class exists to provide safe defaults
650 for RPC calls that are not technically safe to retry normally (due to potential data
651 duplication or other side-effects) but become safe to retry if a condition such as
652 if_metageneration_match is set.
653
654 See the retry.py source code and docstrings in this package (google.cloud.storage.retry) for
655 information on retry types and how to configure them.
656
657 _target_object (Union[ \
658 :class:`~google.cloud.storage.bucket.Bucket`, \
659 :class:`~google.cloud.storage.bucket.blob`, \
660 ]):
661 Object to which future data is to be applied -- only relevant
662 in the context of a batch.
663
664 Returns:
665 dict
666 The JSON resource fetched
667
668 Raises:
669 google.cloud.exceptions.NotFound
670 If the bucket is not found.
671 """
672 return self._connection.api_request(
673 method="PUT",
674 path=path,
675 data=data,
676 query_params=query_params,
677 headers=headers,
678 timeout=timeout,
679 retry=retry,
680 _target_object=_target_object,
681 )
682
683 def _post_resource(
684 self,
685 path,
686 data,
687 query_params=None,
688 headers=None,
689 timeout=_DEFAULT_TIMEOUT,
690 retry=None,
691 _target_object=None,
692 ):
693 """Helper for bucket / blob methods making API 'POST' calls.
694
695 Args:
696 path str:
697 The path of the resource to which to post.
698
699 data dict:
700 The data to be posted.
701
702 query_params Optional[dict]:
703 HTTP query parameters to be passed
704
705 headers Optional[dict]:
706 HTTP headers to be passed
707
708 timeout (Optional[Union[float, Tuple[float, float]]]):
709 The amount of time, in seconds, to wait for the server response.
710
711 Can also be passed as a tuple (connect_timeout, read_timeout).
712 See :meth:`requests.Session.request` documentation for details.
713
714 retry (Optional[Union[google.api_core.retry.Retry, google.cloud.storage.retry.ConditionalRetryPolicy]]):
715 How to retry the RPC. A None value will disable retries.
716 A google.api_core.retry.Retry value will enable retries, and the object will
717 define retriable response codes and errors and configure backoff and timeout options.
718
719 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a Retry object and
720 activates it only if certain conditions are met. This class exists to provide safe defaults
721 for RPC calls that are not technically safe to retry normally (due to potential data
722 duplication or other side-effects) but become safe to retry if a condition such as
723 if_metageneration_match is set.
724
725 See the retry.py source code and docstrings in this package (google.cloud.storage.retry) for
726 information on retry types and how to configure them.
727
728 _target_object (Union[ \
729 :class:`~google.cloud.storage.bucket.Bucket`, \
730 :class:`~google.cloud.storage.bucket.blob`, \
731 ]):
732 Object to which future data is to be applied -- only relevant
733 in the context of a batch.
734
735 Returns:
736 dict
737 The JSON resource returned from the post.
738
739 Raises:
740 google.cloud.exceptions.NotFound
741 If the bucket is not found.
742 """
743
744 return self._connection.api_request(
745 method="POST",
746 path=path,
747 data=data,
748 query_params=query_params,
749 headers=headers,
750 timeout=timeout,
751 retry=retry,
752 _target_object=_target_object,
753 )
754
755 def _delete_resource(
756 self,
757 path,
758 query_params=None,
759 headers=None,
760 timeout=_DEFAULT_TIMEOUT,
761 retry=DEFAULT_RETRY,
762 _target_object=None,
763 ):
764 """Helper for bucket / blob methods making API 'DELETE' calls.
765
766 Args:
767 path str:
768 The path of the resource to delete.
769
770 query_params Optional[dict]:
771 HTTP query parameters to be passed
772
773 headers Optional[dict]:
774 HTTP headers to be passed
775
776 timeout (Optional[Union[float, Tuple[float, float]]]):
777 The amount of time, in seconds, to wait for the server response.
778
779 Can also be passed as a tuple (connect_timeout, read_timeout).
780 See :meth:`requests.Session.request` documentation for details.
781
782 retry (Optional[Union[google.api_core.retry.Retry, google.cloud.storage.retry.ConditionalRetryPolicy]]):
783 How to retry the RPC. A None value will disable retries.
784 A google.api_core.retry.Retry value will enable retries, and the object will
785 define retriable response codes and errors and configure backoff and timeout options.
786
787 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a Retry object and
788 activates it only if certain conditions are met. This class exists to provide safe defaults
789 for RPC calls that are not technically safe to retry normally (due to potential data
790 duplication or other side-effects) but become safe to retry if a condition such as
791 if_metageneration_match is set.
792
793 See the retry.py source code and docstrings in this package (google.cloud.storage.retry) for
794 information on retry types and how to configure them.
795
796 _target_object (Union[ \
797 :class:`~google.cloud.storage.bucket.Bucket`, \
798 :class:`~google.cloud.storage.bucket.blob`, \
799 ]):
800 Object to which future data is to be applied -- only relevant
801 in the context of a batch.
802
803 Returns:
804 dict
805 The JSON resource fetched
806
807 Raises:
808 google.cloud.exceptions.NotFound
809 If the bucket is not found.
810 """
811 return self._connection.api_request(
812 method="DELETE",
813 path=path,
814 query_params=query_params,
815 headers=headers,
816 timeout=timeout,
817 retry=retry,
818 _target_object=_target_object,
819 )
820
821 def _bucket_arg_to_bucket(self, bucket_or_name, generation=None):
822 """Helper to return given bucket or create new by name.
823
824 Args:
825 bucket_or_name (Union[ \
826 :class:`~google.cloud.storage.bucket.Bucket`, \
827 str, \
828 ]):
829 The bucket resource to pass or name to create.
830 generation (Optional[int]):
831 The bucket generation. If generation is specified,
832 bucket_or_name must be a name (str).
833
834 Returns:
835 google.cloud.storage.bucket.Bucket
836 The newly created bucket or the given one.
837 """
838 if isinstance(bucket_or_name, Bucket):
839 if generation:
840 raise ValueError(
841 "The generation can only be specified if a "
842 "name is used to specify a bucket, not a Bucket object. "
843 "Create a new Bucket object with the correct generation "
844 "instead."
845 )
846 bucket = bucket_or_name
847 if bucket.client is None:
848 bucket._client = self
849 else:
850 bucket = Bucket(self, name=bucket_or_name, generation=generation)
851 return bucket
852
853 def get_bucket(
854 self,
855 bucket_or_name,
856 timeout=_DEFAULT_TIMEOUT,
857 if_metageneration_match=None,
858 if_metageneration_not_match=None,
859 retry=DEFAULT_RETRY,
860 *,
861 generation=None,
862 soft_deleted=None,
863 ):
864 """Retrieve a bucket via a GET request.
865
866 See [API reference docs](https://cloud.google.com/storage/docs/json_api/v1/buckets/get) and a [code sample](https://cloud.google.com/storage/docs/samples/storage-get-bucket-metadata#storage_get_bucket_metadata-python).
867
868 Args:
869 bucket_or_name (Union[ \
870 :class:`~google.cloud.storage.bucket.Bucket`, \
871 str, \
872 ]):
873 The bucket resource to pass or name to create.
874
875 timeout (Optional[Union[float, Tuple[float, float]]]):
876 The amount of time, in seconds, to wait for the server response.
877
878 Can also be passed as a tuple (connect_timeout, read_timeout).
879 See :meth:`requests.Session.request` documentation for details.
880
881 if_metageneration_match (Optional[int]):
882 Make the operation conditional on whether the
883 bucket's current metageneration matches the given value.
884
885 if_metageneration_not_match (Optional[int]):
886 Make the operation conditional on whether the bucket's
887 current metageneration does not match the given value.
888
889 retry (Optional[Union[google.api_core.retry.Retry, google.cloud.storage.retry.ConditionalRetryPolicy]]):
890 How to retry the RPC. A None value will disable retries.
891 A google.api_core.retry.Retry value will enable retries, and the object will
892 define retriable response codes and errors and configure backoff and timeout options.
893
894 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a Retry object and
895 activates it only if certain conditions are met. This class exists to provide safe defaults
896 for RPC calls that are not technically safe to retry normally (due to potential data
897 duplication or other side-effects) but become safe to retry if a condition such as
898 if_metageneration_match is set.
899
900 See the retry.py source code and docstrings in this package (google.cloud.storage.retry) for
901 information on retry types and how to configure them.
902
903 generation (Optional[int]):
904 The generation of the bucket. The generation can be used to
905 specify a specific soft-deleted version of the bucket, in
906 conjunction with the ``soft_deleted`` argument below. If
907 ``soft_deleted`` is not True, the generation is unused.
908
909 soft_deleted (Optional[bool]):
910 If True, looks for a soft-deleted bucket. Will only return
911 the bucket metadata if the bucket exists and is in a
912 soft-deleted state. The bucket ``generation`` is required if
913 ``soft_deleted`` is set to True.
914 See: https://cloud.google.com/storage/docs/soft-delete
915
916 Returns:
917 google.cloud.storage.bucket.Bucket
918 The bucket matching the name provided.
919
920 Raises:
921 google.cloud.exceptions.NotFound
922 If the bucket is not found.
923 """
924 with create_trace_span(name="Storage.Client.getBucket"):
925 bucket = self._bucket_arg_to_bucket(bucket_or_name, generation=generation)
926 bucket.reload(
927 client=self,
928 timeout=timeout,
929 if_metageneration_match=if_metageneration_match,
930 if_metageneration_not_match=if_metageneration_not_match,
931 retry=retry,
932 soft_deleted=soft_deleted,
933 )
934 return bucket
935
936 def lookup_bucket(
937 self,
938 bucket_name,
939 timeout=_DEFAULT_TIMEOUT,
940 if_metageneration_match=None,
941 if_metageneration_not_match=None,
942 retry=DEFAULT_RETRY,
943 ):
944 """Get a bucket by name, returning None if not found.
945
946 You can use this if you would rather check for a None value
947 than catching a NotFound exception.
948
949 :type bucket_name: str
950 :param bucket_name: The name of the bucket to get.
951
952 :type timeout: float or tuple
953 :param timeout:
954 (Optional) The amount of time, in seconds, to wait
955 for the server response. See: :ref:`configuring_timeouts`
956
957 :type if_metageneration_match: long
958 :param if_metageneration_match: (Optional) Make the operation conditional on whether the
959 blob's current metageneration matches the given value.
960
961 :type if_metageneration_not_match: long
962 :param if_metageneration_not_match: (Optional) Make the operation conditional on whether the
963 blob's current metageneration does not match the given value.
964
965 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
966 :param retry:
967 (Optional) How to retry the RPC. See: :ref:`configuring_retries`
968
969 :rtype: :class:`google.cloud.storage.bucket.Bucket` or ``NoneType``
970 :returns: The bucket matching the name provided or None if not found.
971 """
972 with create_trace_span(name="Storage.Client.lookupBucket"):
973 try:
974 return self.get_bucket(
975 bucket_name,
976 timeout=timeout,
977 if_metageneration_match=if_metageneration_match,
978 if_metageneration_not_match=if_metageneration_not_match,
979 retry=retry,
980 )
981 except NotFound:
982 return None
983
984 def create_bucket(
985 self,
986 bucket_or_name,
987 requester_pays=None,
988 project=None,
989 user_project=None,
990 location=None,
991 data_locations=None,
992 predefined_acl=None,
993 predefined_default_object_acl=None,
994 enable_object_retention=False,
995 timeout=_DEFAULT_TIMEOUT,
996 retry=DEFAULT_RETRY,
997 ):
998 """Create a new bucket via a POST request.
999
1000 See [API reference docs](https://cloud.google.com/storage/docs/json_api/v1/buckets/insert) and a [code sample](https://cloud.google.com/storage/docs/samples/storage-create-bucket#storage_create_bucket-python).
1001
1002 Args:
1003 bucket_or_name (Union[ \
1004 :class:`~google.cloud.storage.bucket.Bucket`, \
1005 str, \
1006 ]):
1007 The bucket resource to pass or name to create.
1008 requester_pays (bool):
1009 DEPRECATED. Use Bucket().requester_pays instead.
1010 (Optional) Whether requester pays for API requests for
1011 this bucket and its blobs.
1012 project (str):
1013 (Optional) The project under which the bucket is to be created.
1014 If not passed, uses the project set on the client.
1015 user_project (str):
1016 (Optional) The project ID to be billed for API requests
1017 made via created bucket.
1018 location (str):
1019 (Optional) The location of the bucket. If not passed,
1020 the default location, US, will be used. If specifying a dual-region,
1021 `data_locations` should be set in conjunction. See:
1022 https://cloud.google.com/storage/docs/locations
1023 data_locations (list of str):
1024 (Optional) The list of regional locations of a custom dual-region bucket.
1025 Dual-regions require exactly 2 regional locations. See:
1026 https://cloud.google.com/storage/docs/locations
1027 predefined_acl (str):
1028 (Optional) Name of predefined ACL to apply to bucket. See:
1029 https://cloud.google.com/storage/docs/access-control/lists#predefined-acl
1030 predefined_default_object_acl (str):
1031 (Optional) Name of predefined ACL to apply to bucket's objects. See:
1032 https://cloud.google.com/storage/docs/access-control/lists#predefined-acl
1033 enable_object_retention (bool):
1034 (Optional) Whether object retention should be enabled on this bucket. See:
1035 https://cloud.google.com/storage/docs/object-lock
1036 timeout (Optional[Union[float, Tuple[float, float]]]):
1037 The amount of time, in seconds, to wait for the server response.
1038
1039 Can also be passed as a tuple (connect_timeout, read_timeout).
1040 See :meth:`requests.Session.request` documentation for details.
1041
1042 retry (Optional[Union[google.api_core.retry.Retry, google.cloud.storage.retry.ConditionalRetryPolicy]]):
1043 How to retry the RPC. A None value will disable retries.
1044 A google.api_core.retry.Retry value will enable retries, and the object will
1045 define retriable response codes and errors and configure backoff and timeout options.
1046
1047 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a Retry object and
1048 activates it only if certain conditions are met. This class exists to provide safe defaults
1049 for RPC calls that are not technically safe to retry normally (due to potential data
1050 duplication or other side-effects) but become safe to retry if a condition such as
1051 if_metageneration_match is set.
1052
1053 See the retry.py source code and docstrings in this package (google.cloud.storage.retry) for
1054 information on retry types and how to configure them.
1055
1056 Returns:
1057 google.cloud.storage.bucket.Bucket
1058 The newly created bucket.
1059
1060 Raises:
1061 google.cloud.exceptions.Conflict
1062 If the bucket already exists.
1063 """
1064 with create_trace_span(name="Storage.Client.createBucket"):
1065 bucket = self._bucket_arg_to_bucket(bucket_or_name)
1066 query_params = {}
1067
1068 if project is None:
1069 project = self.project
1070
1071 # Use no project if STORAGE_EMULATOR_HOST is set
1072 if self._is_emulator_set:
1073 if project is None:
1074 project = _get_environ_project()
1075 if project is None:
1076 project = "<none>"
1077
1078 # Only include the project parameter if a project is set.
1079 # If a project is not set, falls back to API validation (BadRequest).
1080 if project is not None:
1081 query_params = {"project": project}
1082
1083 if requester_pays is not None:
1084 warnings.warn(
1085 "requester_pays arg is deprecated. Use Bucket().requester_pays instead.",
1086 PendingDeprecationWarning,
1087 stacklevel=1,
1088 )
1089 bucket.requester_pays = requester_pays
1090
1091 if predefined_acl is not None:
1092 predefined_acl = BucketACL.validate_predefined(predefined_acl)
1093 query_params["predefinedAcl"] = predefined_acl
1094
1095 if predefined_default_object_acl is not None:
1096 predefined_default_object_acl = DefaultObjectACL.validate_predefined(
1097 predefined_default_object_acl
1098 )
1099 query_params[
1100 "predefinedDefaultObjectAcl"
1101 ] = predefined_default_object_acl
1102
1103 if user_project is not None:
1104 query_params["userProject"] = user_project
1105
1106 if enable_object_retention:
1107 query_params["enableObjectRetention"] = enable_object_retention
1108
1109 properties = {key: bucket._properties[key] for key in bucket._changes}
1110 properties["name"] = bucket.name
1111
1112 if location is not None:
1113 properties["location"] = location
1114
1115 if data_locations is not None:
1116 properties["customPlacementConfig"] = {"dataLocations": data_locations}
1117
1118 api_response = self._post_resource(
1119 "/b",
1120 properties,
1121 query_params=query_params,
1122 timeout=timeout,
1123 retry=retry,
1124 _target_object=bucket,
1125 )
1126
1127 bucket._set_properties(api_response)
1128 return bucket
1129
1130 def download_blob_to_file(
1131 self,
1132 blob_or_uri,
1133 file_obj,
1134 start=None,
1135 end=None,
1136 raw_download=False,
1137 if_etag_match=None,
1138 if_etag_not_match=None,
1139 if_generation_match=None,
1140 if_generation_not_match=None,
1141 if_metageneration_match=None,
1142 if_metageneration_not_match=None,
1143 timeout=_DEFAULT_TIMEOUT,
1144 checksum="auto",
1145 retry=DEFAULT_RETRY,
1146 single_shot_download=False,
1147 ):
1148 """Download the contents of a blob object or blob URI into a file-like object.
1149
1150 See https://cloud.google.com/storage/docs/downloading-objects
1151
1152 Args:
1153 blob_or_uri (Union[ \
1154 :class:`~google.cloud.storage.blob.Blob`, \
1155 str, \
1156 ]):
1157 The blob resource to pass or URI to download.
1158
1159 file_obj (file):
1160 A file handle to which to write the blob's data.
1161
1162 start (int):
1163 (Optional) The first byte in a range to be downloaded.
1164
1165 end (int):
1166 (Optional) The last byte in a range to be downloaded.
1167
1168 raw_download (bool):
1169 (Optional) If true, download the object without any expansion.
1170
1171 if_etag_match (Union[str, Set[str]]):
1172 (Optional) See :ref:`using-if-etag-match`
1173
1174 if_etag_not_match (Union[str, Set[str]]):
1175 (Optional) See :ref:`using-if-etag-not-match`
1176
1177 if_generation_match (long):
1178 (Optional) See :ref:`using-if-generation-match`
1179
1180 if_generation_not_match (long):
1181 (Optional) See :ref:`using-if-generation-not-match`
1182
1183 if_metageneration_match (long):
1184 (Optional) See :ref:`using-if-metageneration-match`
1185
1186 if_metageneration_not_match (long):
1187 (Optional) See :ref:`using-if-metageneration-not-match`
1188
1189 timeout ([Union[float, Tuple[float, float]]]):
1190 (Optional) The amount of time, in seconds, to wait
1191 for the server response. See: :ref:`configuring_timeouts`
1192
1193 checksum (str):
1194 (Optional) The type of checksum to compute to verify the integrity
1195 of the object. The response headers must contain a checksum of the
1196 requested type. If the headers lack an appropriate checksum (for
1197 instance in the case of transcoded or ranged downloads where the
1198 remote service does not know the correct checksum, including
1199 downloads where chunk_size is set) an INFO-level log will be
1200 emitted. Supported values are "md5", "crc32c", "auto" and None.
1201 The default is "auto", which will try to detect if the C
1202 extension for crc32c is installed and fall back to md5 otherwise.
1203
1204 retry (google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy)
1205 (Optional) How to retry the RPC. A None value will disable
1206 retries. A google.api_core.retry.Retry value will enable retries,
1207 and the object will define retriable response codes and errors and
1208 configure backoff and timeout options.
1209
1210 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a
1211 Retry object and activates it only if certain conditions are met.
1212 This class exists to provide safe defaults for RPC calls that are
1213 not technically safe to retry normally (due to potential data
1214 duplication or other side-effects) but become safe to retry if a
1215 condition such as if_metageneration_match is set.
1216
1217 See the retry.py source code and docstrings in this package
1218 (google.cloud.storage.retry) for information on retry types and how
1219 to configure them.
1220
1221 single_shot_download (bool):
1222 (Optional) If true, download the object in a single request.
1223 """
1224 with create_trace_span(name="Storage.Client.downloadBlobToFile"):
1225 if not isinstance(blob_or_uri, Blob):
1226 blob_or_uri = Blob.from_uri(blob_or_uri)
1227
1228 blob_or_uri._prep_and_do_download(
1229 file_obj,
1230 client=self,
1231 start=start,
1232 end=end,
1233 raw_download=raw_download,
1234 if_etag_match=if_etag_match,
1235 if_etag_not_match=if_etag_not_match,
1236 if_generation_match=if_generation_match,
1237 if_generation_not_match=if_generation_not_match,
1238 if_metageneration_match=if_metageneration_match,
1239 if_metageneration_not_match=if_metageneration_not_match,
1240 timeout=timeout,
1241 checksum=checksum,
1242 retry=retry,
1243 single_shot_download=single_shot_download,
1244 )
1245
1246 def list_blobs(
1247 self,
1248 bucket_or_name,
1249 max_results=None,
1250 page_token=None,
1251 prefix=None,
1252 delimiter=None,
1253 start_offset=None,
1254 end_offset=None,
1255 include_trailing_delimiter=None,
1256 versions=None,
1257 projection="noAcl",
1258 fields=None,
1259 page_size=None,
1260 timeout=_DEFAULT_TIMEOUT,
1261 retry=DEFAULT_RETRY,
1262 match_glob=None,
1263 include_folders_as_prefixes=None,
1264 soft_deleted=None,
1265 ):
1266 """Return an iterator used to find blobs in the bucket.
1267
1268 If :attr:`user_project` is set, bills the API request to that project.
1269
1270 .. note::
1271 List prefixes (directories) in a bucket using a prefix and delimiter.
1272 See a [code sample](https://cloud.google.com/storage/docs/samples/storage-list-files-with-prefix#storage_list_files_with_prefix-python)
1273 listing objects using a prefix filter.
1274
1275 Args:
1276 bucket_or_name (Union[ \
1277 :class:`~google.cloud.storage.bucket.Bucket`, \
1278 str, \
1279 ]):
1280 The bucket resource to pass or name to create.
1281
1282 max_results (int):
1283 (Optional) The maximum number of blobs to return.
1284
1285 page_token (str):
1286 (Optional) If present, return the next batch of blobs, using the
1287 value, which must correspond to the ``nextPageToken`` value
1288 returned in the previous response. Deprecated: use the ``pages``
1289 property of the returned iterator instead of manually passing the
1290 token.
1291
1292 prefix (str):
1293 (Optional) Prefix used to filter blobs.
1294
1295 delimiter (str):
1296 (Optional) Delimiter, used with ``prefix`` to
1297 emulate hierarchy.
1298
1299 start_offset (str):
1300 (Optional) Filter results to objects whose names are
1301 lexicographically equal to or after ``startOffset``. If
1302 ``endOffset`` is also set, the objects listed will have names
1303 between ``startOffset`` (inclusive) and ``endOffset``
1304 (exclusive).
1305
1306 end_offset (str):
1307 (Optional) Filter results to objects whose names are
1308 lexicographically before ``endOffset``. If ``startOffset`` is
1309 also set, the objects listed will have names between
1310 ``startOffset`` (inclusive) and ``endOffset`` (exclusive).
1311
1312 include_trailing_delimiter (boolean):
1313 (Optional) If true, objects that end in exactly one instance of
1314 ``delimiter`` will have their metadata included in ``items`` in
1315 addition to ``prefixes``.
1316
1317 versions (bool):
1318 (Optional) Whether object versions should be returned
1319 as separate blobs.
1320
1321 projection (str):
1322 (Optional) If used, must be 'full' or 'noAcl'.
1323 Defaults to ``'noAcl'``. Specifies the set of
1324 properties to return.
1325
1326 fields (str):
1327 (Optional) Selector specifying which fields to include
1328 in a partial response. Must be a list of fields. For
1329 example to get a partial response with just the next
1330 page token and the name and language of each blob returned:
1331 ``'items(name,contentLanguage),nextPageToken'``.
1332 See: https://cloud.google.com/storage/docs/json_api/v1/parameters#fields
1333
1334 page_size (int):
1335 (Optional) Maximum number of blobs to return in each page.
1336 Defaults to a value set by the API.
1337
1338 timeout (Optional[Union[float, Tuple[float, float]]]):
1339 The amount of time, in seconds, to wait for the server response.
1340
1341 Can also be passed as a tuple (connect_timeout, read_timeout).
1342 See :meth:`requests.Session.request` documentation for details.
1343
1344 retry (Optional[Union[google.api_core.retry.Retry, google.cloud.storage.retry.ConditionalRetryPolicy]]):
1345 How to retry the RPC. A None value will disable retries.
1346 A google.api_core.retry.Retry value will enable retries, and the object will
1347 define retriable response codes and errors and configure backoff and timeout options.
1348
1349 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a Retry object and
1350 activates it only if certain conditions are met. This class exists to provide safe defaults
1351 for RPC calls that are not technically safe to retry normally (due to potential data
1352 duplication or other side-effects) but become safe to retry if a condition such as
1353 if_metageneration_match is set.
1354
1355 See the retry.py source code and docstrings in this package (google.cloud.storage.retry) for
1356 information on retry types and how to configure them.
1357
1358 match_glob (str):
1359 (Optional) A glob pattern used to filter results (for example, foo*bar).
1360 The string value must be UTF-8 encoded. See:
1361 https://cloud.google.com/storage/docs/json_api/v1/objects/list#list-object-glob
1362
1363 include_folders_as_prefixes (bool):
1364 (Optional) If true, includes Folders and Managed Folders in the set of
1365 ``prefixes`` returned by the query. Only applicable if ``delimiter`` is set to /.
1366 See: https://cloud.google.com/storage/docs/managed-folders
1367
1368 soft_deleted (bool):
1369 (Optional) If true, only soft-deleted objects will be listed as distinct results in order of increasing
1370 generation number. This parameter can only be used successfully if the bucket has a soft delete policy.
1371 Note ``soft_deleted`` and ``versions`` cannot be set to True simultaneously. See:
1372 https://cloud.google.com/storage/docs/soft-delete
1373
1374 Returns:
1375 Iterator of all :class:`~google.cloud.storage.blob.Blob`
1376 in this bucket matching the arguments. The RPC call
1377 returns a response when the iterator is consumed.
1378
1379 As part of the response, you'll also get back an iterator.prefixes entity that lists object names
1380 up to and including the requested delimiter. Duplicate entries are omitted from this list.
1381 """
1382 with create_trace_span(name="Storage.Client.listBlobs"):
1383 bucket = self._bucket_arg_to_bucket(bucket_or_name)
1384
1385 extra_params = {"projection": projection}
1386
1387 if prefix is not None:
1388 extra_params["prefix"] = prefix
1389
1390 if delimiter is not None:
1391 extra_params["delimiter"] = delimiter
1392
1393 if match_glob is not None:
1394 extra_params["matchGlob"] = match_glob
1395
1396 if start_offset is not None:
1397 extra_params["startOffset"] = start_offset
1398
1399 if end_offset is not None:
1400 extra_params["endOffset"] = end_offset
1401
1402 if include_trailing_delimiter is not None:
1403 extra_params["includeTrailingDelimiter"] = include_trailing_delimiter
1404
1405 if versions is not None:
1406 extra_params["versions"] = versions
1407
1408 if fields is not None:
1409 extra_params["fields"] = fields
1410
1411 if include_folders_as_prefixes is not None:
1412 extra_params["includeFoldersAsPrefixes"] = include_folders_as_prefixes
1413
1414 if soft_deleted is not None:
1415 extra_params["softDeleted"] = soft_deleted
1416
1417 if bucket.user_project is not None:
1418 extra_params["userProject"] = bucket.user_project
1419
1420 path = bucket.path + "/o"
1421 iterator = self._list_resource(
1422 path,
1423 _item_to_blob,
1424 page_token=page_token,
1425 max_results=max_results,
1426 extra_params=extra_params,
1427 page_start=_blobs_page_start,
1428 page_size=page_size,
1429 timeout=timeout,
1430 retry=retry,
1431 )
1432 iterator.bucket = bucket
1433 iterator.prefixes = set()
1434 return iterator
1435
1436 def list_buckets(
1437 self,
1438 max_results=None,
1439 page_token=None,
1440 prefix=None,
1441 projection="noAcl",
1442 fields=None,
1443 project=None,
1444 page_size=None,
1445 timeout=_DEFAULT_TIMEOUT,
1446 retry=DEFAULT_RETRY,
1447 *,
1448 soft_deleted=None,
1449 ):
1450 """Get all buckets in the project associated to the client.
1451
1452 This will not populate the list of blobs available in each
1453 bucket.
1454
1455 See [API reference docs](https://cloud.google.com/storage/docs/json_api/v1/buckets/list) and a [code sample](https://cloud.google.com/storage/docs/samples/storage-list-buckets#storage_list_buckets-python).
1456
1457 :type max_results: int
1458 :param max_results: (Optional) The maximum number of buckets to return.
1459
1460 :type page_token: str
1461 :param page_token:
1462 (Optional) If present, return the next batch of buckets, using the
1463 value, which must correspond to the ``nextPageToken`` value
1464 returned in the previous response. Deprecated: use the ``pages``
1465 property of the returned iterator instead of manually passing the
1466 token.
1467
1468 :type prefix: str
1469 :param prefix: (Optional) Filter results to buckets whose names begin
1470 with this prefix.
1471
1472 :type projection: str
1473 :param projection:
1474 (Optional) Specifies the set of properties to return. If used, must
1475 be 'full' or 'noAcl'. Defaults to 'noAcl'.
1476
1477 :type fields: str
1478 :param fields:
1479 (Optional) Selector specifying which fields to include in a partial
1480 response. Must be a list of fields. For example to get a partial
1481 response with just the next page token and the language of each
1482 bucket returned: 'items/id,nextPageToken'
1483
1484 :type project: str
1485 :param project: (Optional) The project whose buckets are to be listed.
1486 If not passed, uses the project set on the client.
1487
1488 :type page_size: int
1489 :param page_size: (Optional) Maximum number of buckets to return in each page.
1490 Defaults to a value set by the API.
1491
1492 :type timeout: float or tuple
1493 :param timeout:
1494 (Optional) The amount of time, in seconds, to wait
1495 for the server response. See: :ref:`configuring_timeouts`
1496
1497 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
1498 :param retry:
1499 (Optional) How to retry the RPC. See: :ref:`configuring_retries`
1500
1501 :type soft_deleted: bool
1502 :param soft_deleted:
1503 (Optional) If true, only soft-deleted buckets will be listed as distinct results in order of increasing
1504 generation number. This parameter can only be used successfully if the bucket has a soft delete policy.
1505 See: https://cloud.google.com/storage/docs/soft-delete
1506
1507 :rtype: :class:`~google.api_core.page_iterator.Iterator`
1508 :raises ValueError: if both ``project`` is ``None`` and the client's
1509 project is also ``None``.
1510 :returns: Iterator of all :class:`~google.cloud.storage.bucket.Bucket`
1511 belonging to this project.
1512 """
1513 with create_trace_span(name="Storage.Client.listBuckets"):
1514 extra_params = {}
1515
1516 if project is None:
1517 project = self.project
1518
1519 # Use no project if STORAGE_EMULATOR_HOST is set
1520 if self._is_emulator_set:
1521 if project is None:
1522 project = _get_environ_project()
1523 if project is None:
1524 project = "<none>"
1525
1526 # Only include the project parameter if a project is set.
1527 # If a project is not set, falls back to API validation (BadRequest).
1528 if project is not None:
1529 extra_params = {"project": project}
1530
1531 if prefix is not None:
1532 extra_params["prefix"] = prefix
1533
1534 extra_params["projection"] = projection
1535
1536 if fields is not None:
1537 extra_params["fields"] = fields
1538
1539 if soft_deleted is not None:
1540 extra_params["softDeleted"] = soft_deleted
1541
1542 return self._list_resource(
1543 "/b",
1544 _item_to_bucket,
1545 page_token=page_token,
1546 max_results=max_results,
1547 extra_params=extra_params,
1548 page_size=page_size,
1549 timeout=timeout,
1550 retry=retry,
1551 )
1552
1553 def restore_bucket(
1554 self,
1555 bucket_name,
1556 generation,
1557 projection="noAcl",
1558 if_metageneration_match=None,
1559 if_metageneration_not_match=None,
1560 timeout=_DEFAULT_TIMEOUT,
1561 retry=DEFAULT_RETRY,
1562 ):
1563 """Restores a soft-deleted bucket.
1564
1565 :type bucket_name: str
1566 :param bucket_name: The name of the bucket to be restored.
1567
1568 :type generation: int
1569 :param generation: Selects the specific revision of the bucket.
1570
1571 :type projection: str
1572 :param projection:
1573 (Optional) Specifies the set of properties to return. If used, must
1574 be 'full' or 'noAcl'. Defaults to 'noAcl'.
1575
1576 if_metageneration_match (Optional[int]):
1577 Make the operation conditional on whether the
1578 blob's current metageneration matches the given value.
1579
1580 if_metageneration_not_match (Optional[int]):
1581 Make the operation conditional on whether the blob's
1582 current metageneration does not match the given value.
1583
1584 :type timeout: float or tuple
1585 :param timeout:
1586 (Optional) The amount of time, in seconds, to wait
1587 for the server response. See: :ref:`configuring_timeouts`
1588
1589 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
1590 :param retry:
1591 (Optional) How to retry the RPC.
1592
1593 Users can configure non-default retry behavior. A ``None`` value will
1594 disable retries. See [Configuring Retries](https://cloud.google.com/python/docs/reference/storage/latest/retry_timeout).
1595
1596 :rtype: :class:`google.cloud.storage.bucket.Bucket`
1597 :returns: The restored Bucket.
1598 """
1599 query_params = {"generation": generation, "projection": projection}
1600
1601 _add_generation_match_parameters(
1602 query_params,
1603 if_metageneration_match=if_metageneration_match,
1604 if_metageneration_not_match=if_metageneration_not_match,
1605 )
1606
1607 bucket = self.bucket(bucket_name)
1608 api_response = self._post_resource(
1609 f"{bucket.path}/restore",
1610 None,
1611 query_params=query_params,
1612 timeout=timeout,
1613 retry=retry,
1614 )
1615 bucket._set_properties(api_response)
1616 return bucket
1617
1618 def create_hmac_key(
1619 self,
1620 service_account_email,
1621 project_id=None,
1622 user_project=None,
1623 timeout=_DEFAULT_TIMEOUT,
1624 retry=None,
1625 ):
1626 """Create an HMAC key for a service account.
1627
1628 :type service_account_email: str
1629 :param service_account_email: e-mail address of the service account
1630
1631 :type project_id: str
1632 :param project_id: (Optional) Explicit project ID for the key.
1633 Defaults to the client's project.
1634
1635 :type user_project: str
1636 :param user_project: (Optional) This parameter is currently ignored.
1637
1638 :type timeout: float or tuple
1639 :param timeout:
1640 (Optional) The amount of time, in seconds, to wait
1641 for the server response. See: :ref:`configuring_timeouts`
1642
1643 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
1644 :param retry: (Optional) How to retry the RPC. A None value will disable retries.
1645 A google.api_core.retry.Retry value will enable retries, and the object will
1646 define retriable response codes and errors and configure backoff and timeout options.
1647
1648 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a Retry object and
1649 activates it only if certain conditions are met. This class exists to provide safe defaults
1650 for RPC calls that are not technically safe to retry normally (due to potential data
1651 duplication or other side-effects) but become safe to retry if a condition such as
1652 if_metageneration_match is set.
1653
1654 See the retry.py source code and docstrings in this package (google.cloud.storage.retry) for
1655 information on retry types and how to configure them.
1656
1657 :rtype:
1658 Tuple[:class:`~google.cloud.storage.hmac_key.HMACKeyMetadata`, str]
1659 :returns: metadata for the created key, plus the bytes of the key's secret, which is an 40-character base64-encoded string.
1660 """
1661 with create_trace_span(name="Storage.Client.createHmacKey"):
1662 if project_id is None:
1663 project_id = self.project
1664
1665 path = f"/projects/{project_id}/hmacKeys"
1666 qs_params = {"serviceAccountEmail": service_account_email}
1667
1668 if user_project is not None:
1669 qs_params["userProject"] = user_project
1670
1671 api_response = self._post_resource(
1672 path,
1673 None,
1674 query_params=qs_params,
1675 timeout=timeout,
1676 retry=retry,
1677 )
1678 metadata = HMACKeyMetadata(self)
1679 metadata._properties = api_response["metadata"]
1680 secret = api_response["secret"]
1681 return metadata, secret
1682
1683 def list_hmac_keys(
1684 self,
1685 max_results=None,
1686 service_account_email=None,
1687 show_deleted_keys=None,
1688 project_id=None,
1689 user_project=None,
1690 timeout=_DEFAULT_TIMEOUT,
1691 retry=DEFAULT_RETRY,
1692 ):
1693 """List HMAC keys for a project.
1694
1695 :type max_results: int
1696 :param max_results:
1697 (Optional) Max number of keys to return in a given page.
1698
1699 :type service_account_email: str
1700 :param service_account_email:
1701 (Optional) Limit keys to those created by the given service account.
1702
1703 :type show_deleted_keys: bool
1704 :param show_deleted_keys:
1705 (Optional) Included deleted keys in the list. Default is to
1706 exclude them.
1707
1708 :type project_id: str
1709 :param project_id: (Optional) Explicit project ID for the key.
1710 Defaults to the client's project.
1711
1712 :type user_project: str
1713 :param user_project: (Optional) This parameter is currently ignored.
1714
1715 :type timeout: float or tuple
1716 :param timeout:
1717 (Optional) The amount of time, in seconds, to wait
1718 for the server response. See: :ref:`configuring_timeouts`
1719
1720 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
1721 :param retry:
1722 (Optional) How to retry the RPC. See: :ref:`configuring_retries`
1723
1724 :rtype:
1725 Tuple[:class:`~google.cloud.storage.hmac_key.HMACKeyMetadata`, str]
1726 :returns: metadata for the created key, plus the bytes of the key's secret, which is an 40-character base64-encoded string.
1727 """
1728 with create_trace_span(name="Storage.Client.listHmacKeys"):
1729 if project_id is None:
1730 project_id = self.project
1731
1732 path = f"/projects/{project_id}/hmacKeys"
1733 extra_params = {}
1734
1735 if service_account_email is not None:
1736 extra_params["serviceAccountEmail"] = service_account_email
1737
1738 if show_deleted_keys is not None:
1739 extra_params["showDeletedKeys"] = show_deleted_keys
1740
1741 if user_project is not None:
1742 extra_params["userProject"] = user_project
1743
1744 return self._list_resource(
1745 path,
1746 _item_to_hmac_key_metadata,
1747 max_results=max_results,
1748 extra_params=extra_params,
1749 timeout=timeout,
1750 retry=retry,
1751 )
1752
1753 def get_hmac_key_metadata(
1754 self, access_id, project_id=None, user_project=None, timeout=_DEFAULT_TIMEOUT
1755 ):
1756 """Return a metadata instance for the given HMAC key.
1757
1758 :type access_id: str
1759 :param access_id: Unique ID of an existing key.
1760
1761 :type project_id: str
1762 :param project_id: (Optional) Project ID of an existing key.
1763 Defaults to client's project.
1764
1765 :type timeout: float or tuple
1766 :param timeout:
1767 (Optional) The amount of time, in seconds, to wait
1768 for the server response. See: :ref:`configuring_timeouts`
1769
1770 :type user_project: str
1771 :param user_project: (Optional) This parameter is currently ignored.
1772 """
1773 with create_trace_span(name="Storage.Client.getHmacKeyMetadata"):
1774 metadata = HMACKeyMetadata(self, access_id, project_id, user_project)
1775 metadata.reload(timeout=timeout) # raises NotFound for missing key
1776 return metadata
1777
1778 def generate_signed_post_policy_v4(
1779 self,
1780 bucket_name,
1781 blob_name,
1782 expiration,
1783 conditions=None,
1784 fields=None,
1785 credentials=None,
1786 virtual_hosted_style=False,
1787 bucket_bound_hostname=None,
1788 scheme="http",
1789 service_account_email=None,
1790 access_token=None,
1791 ):
1792 """Generate a V4 signed policy object. Generated policy object allows user to upload objects with a POST request.
1793
1794 .. note::
1795
1796 Assumes ``credentials`` implements the
1797 :class:`google.auth.credentials.Signing` interface. Also assumes
1798 ``credentials`` has a ``service_account_email`` property which
1799 identifies the credentials.
1800
1801 See a [code sample](https://github.com/googleapis/python-storage/blob/main/samples/snippets/storage_generate_signed_post_policy_v4.py).
1802
1803 :type bucket_name: str
1804 :param bucket_name: Bucket name.
1805
1806 :type blob_name: str
1807 :param blob_name: Object name.
1808
1809 :type expiration: Union[Integer, datetime.datetime, datetime.timedelta]
1810 :param expiration: Policy expiration time. If a ``datetime`` instance is
1811 passed without an explicit ``tzinfo`` set, it will be
1812 assumed to be ``UTC``.
1813
1814 :type conditions: list
1815 :param conditions: (Optional) List of POST policy conditions, which are
1816 used to restrict what is allowed in the request.
1817
1818 :type fields: dict
1819 :param fields: (Optional) Additional elements to include into request.
1820
1821 :type credentials: :class:`google.auth.credentials.Signing`
1822 :param credentials: (Optional) Credentials object with an associated private
1823 key to sign text.
1824
1825 :type virtual_hosted_style: bool
1826 :param virtual_hosted_style:
1827 (Optional) If True, construct the URL relative to the bucket
1828 virtual hostname, e.g., '<bucket-name>.storage.googleapis.com'.
1829 Incompatible with bucket_bound_hostname.
1830
1831 :type bucket_bound_hostname: str
1832 :param bucket_bound_hostname:
1833 (Optional) If passed, construct the URL relative to the bucket-bound hostname.
1834 Value can be bare or with a scheme, e.g., 'example.com' or 'http://example.com'.
1835 Incompatible with virtual_hosted_style.
1836 See: https://cloud.google.com/storage/docs/request-endpoints#cname
1837
1838 :type scheme: str
1839 :param scheme:
1840 (Optional) If ``bucket_bound_hostname`` is passed as a bare hostname, use
1841 this value as a scheme. ``https`` will work only when using a CDN.
1842 Defaults to ``"http"``.
1843
1844 :type service_account_email: str
1845 :param service_account_email: (Optional) E-mail address of the service account.
1846
1847 :type access_token: str
1848 :param access_token: (Optional) Access token for a service account.
1849
1850 :raises: :exc:`ValueError` when mutually exclusive arguments are used.
1851
1852 :rtype: dict
1853 :returns: Signed POST policy.
1854 """
1855 if virtual_hosted_style and bucket_bound_hostname:
1856 raise ValueError(
1857 "Only one of virtual_hosted_style and bucket_bound_hostname "
1858 "can be specified."
1859 )
1860
1861 credentials = self._credentials if credentials is None else credentials
1862 client_email = service_account_email
1863 if not access_token or not service_account_email:
1864 ensure_signed_credentials(credentials)
1865 client_email = credentials.signer_email
1866
1867 # prepare policy conditions and fields
1868 timestamp, datestamp = get_v4_now_dtstamps()
1869
1870 x_goog_credential = "{email}/{datestamp}/auto/storage/goog4_request".format(
1871 email=client_email, datestamp=datestamp
1872 )
1873 required_conditions = [
1874 {"bucket": bucket_name},
1875 {"key": blob_name},
1876 {"x-goog-date": timestamp},
1877 {"x-goog-credential": x_goog_credential},
1878 {"x-goog-algorithm": "GOOG4-RSA-SHA256"},
1879 ]
1880
1881 conditions = conditions or []
1882 policy_fields = {}
1883 for key, value in sorted((fields or {}).items()):
1884 if not key.startswith("x-ignore-"):
1885 policy_fields[key] = value
1886 conditions.append({key: value})
1887
1888 conditions += required_conditions
1889
1890 # calculate policy expiration time
1891 now = _NOW(_UTC).replace(tzinfo=None)
1892 if expiration is None:
1893 expiration = now + datetime.timedelta(hours=1)
1894
1895 policy_expires = now + datetime.timedelta(
1896 seconds=get_expiration_seconds_v4(expiration)
1897 )
1898
1899 # encode policy for signing
1900 policy = json.dumps(
1901 collections.OrderedDict(
1902 sorted(
1903 {
1904 "conditions": conditions,
1905 "expiration": policy_expires.isoformat() + "Z",
1906 }.items()
1907 )
1908 ),
1909 separators=(",", ":"),
1910 )
1911 str_to_sign = base64.b64encode(policy.encode("utf-8"))
1912
1913 # sign the policy and get its cryptographic signature
1914 if access_token and service_account_email:
1915 signature = _sign_message(str_to_sign, access_token, service_account_email)
1916 signature_bytes = base64.b64decode(signature)
1917 else:
1918 signature_bytes = credentials.sign_bytes(str_to_sign)
1919
1920 # get hexadecimal representation of the signature
1921 signature = binascii.hexlify(signature_bytes).decode("utf-8")
1922
1923 policy_fields.update(
1924 {
1925 "key": blob_name,
1926 "x-goog-algorithm": "GOOG4-RSA-SHA256",
1927 "x-goog-credential": x_goog_credential,
1928 "x-goog-date": timestamp,
1929 "x-goog-signature": signature,
1930 "policy": str_to_sign.decode("utf-8"),
1931 }
1932 )
1933 # designate URL
1934 if virtual_hosted_style:
1935 url = _virtual_hosted_style_base_url(
1936 self.api_endpoint, bucket_name, trailing_slash=True
1937 )
1938 elif bucket_bound_hostname:
1939 url = f"{_bucket_bound_hostname_url(bucket_bound_hostname, scheme)}/"
1940 else:
1941 url = f"{self.api_endpoint}/{bucket_name}/"
1942
1943 return {"url": url, "fields": policy_fields}
1944
1945
1946def _item_to_bucket(iterator, item):
1947 """Convert a JSON bucket to the native object.
1948
1949 :type iterator: :class:`~google.api_core.page_iterator.Iterator`
1950 :param iterator: The iterator that has retrieved the item.
1951
1952 :type item: dict
1953 :param item: An item to be converted to a bucket.
1954
1955 :rtype: :class:`.Bucket`
1956 :returns: The next bucket in the page.
1957 """
1958 name = item.get("name")
1959 bucket = Bucket(iterator.client, name)
1960 bucket._set_properties(item)
1961 return bucket
1962
1963
1964def _item_to_hmac_key_metadata(iterator, item):
1965 """Convert a JSON key metadata resource to the native object.
1966
1967 :type iterator: :class:`~google.api_core.page_iterator.Iterator`
1968 :param iterator: The iterator that has retrieved the item.
1969
1970 :type item: dict
1971 :param item: An item to be converted to a key metadata instance.
1972
1973 :rtype: :class:`~google.cloud.storage.hmac_key.HMACKeyMetadata`
1974 :returns: The next key metadata instance in the page.
1975 """
1976 metadata = HMACKeyMetadata(iterator.client)
1977 metadata._properties = item
1978 return metadata