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