Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/google/cloud/storage/bucket.py: 35%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

852 statements  

1# Copyright 2014 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"""Create / interact with Google Cloud Storage buckets.""" 

16 

17import base64 

18import copy 

19import datetime 

20import json 

21from urllib.parse import urlsplit 

22import warnings 

23 

24from google.api_core import datetime_helpers 

25from google.cloud._helpers import _datetime_to_rfc3339 

26from google.cloud._helpers import _rfc3339_nanos_to_datetime 

27from google.cloud.exceptions import NotFound 

28from google.api_core.iam import Policy 

29from google.cloud.storage import _signing 

30from google.cloud.storage._helpers import _add_etag_match_headers 

31from google.cloud.storage._helpers import _add_generation_match_parameters 

32from google.cloud.storage._helpers import _NOW 

33from google.cloud.storage._helpers import _PropertyMixin 

34from google.cloud.storage._helpers import _UTC 

35from google.cloud.storage._helpers import _scalar_property 

36from google.cloud.storage._helpers import _validate_name 

37from google.cloud.storage._signing import generate_signed_url_v2 

38from google.cloud.storage._signing import generate_signed_url_v4 

39from google.cloud.storage._helpers import _bucket_bound_hostname_url 

40from google.cloud.storage._helpers import _virtual_hosted_style_base_url 

41from google.cloud.storage._opentelemetry_tracing import create_trace_span 

42from google.cloud.storage.acl import BucketACL 

43from google.cloud.storage.acl import DefaultObjectACL 

44from google.cloud.storage.blob import Blob 

45from google.cloud.storage.constants import _DEFAULT_TIMEOUT 

46from google.cloud.storage.constants import ARCHIVE_STORAGE_CLASS 

47from google.cloud.storage.constants import COLDLINE_STORAGE_CLASS 

48from google.cloud.storage.constants import DUAL_REGION_LOCATION_TYPE 

49from google.cloud.storage.constants import ( 

50 DURABLE_REDUCED_AVAILABILITY_LEGACY_STORAGE_CLASS, 

51) 

52from google.cloud.storage.constants import MULTI_REGIONAL_LEGACY_STORAGE_CLASS 

53from google.cloud.storage.constants import MULTI_REGION_LOCATION_TYPE 

54from google.cloud.storage.constants import NEARLINE_STORAGE_CLASS 

55from google.cloud.storage.constants import PUBLIC_ACCESS_PREVENTION_INHERITED 

56from google.cloud.storage.constants import REGIONAL_LEGACY_STORAGE_CLASS 

57from google.cloud.storage.constants import REGION_LOCATION_TYPE 

58from google.cloud.storage.constants import STANDARD_STORAGE_CLASS 

59from google.cloud.storage.ip_filter import IPFilter 

60from google.cloud.storage.notification import BucketNotification 

61from google.cloud.storage.notification import NONE_PAYLOAD_FORMAT 

62from google.cloud.storage.retry import DEFAULT_RETRY 

63from google.cloud.storage.retry import DEFAULT_RETRY_IF_GENERATION_SPECIFIED 

64from google.cloud.storage.retry import DEFAULT_RETRY_IF_ETAG_IN_JSON 

65from google.cloud.storage.retry import DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED 

66 

67 

68_UBLA_BPO_ENABLED_MESSAGE = ( 

69 "Pass only one of 'uniform_bucket_level_access_enabled' / " 

70 "'bucket_policy_only_enabled' to 'IAMConfiguration'." 

71) 

72_BPO_ENABLED_MESSAGE = ( 

73 "'IAMConfiguration.bucket_policy_only_enabled' is deprecated. " 

74 "Instead, use 'IAMConfiguration.uniform_bucket_level_access_enabled'." 

75) 

76_UBLA_BPO_LOCK_TIME_MESSAGE = ( 

77 "Pass only one of 'uniform_bucket_level_access_lock_time' / " 

78 "'bucket_policy_only_lock_time' to 'IAMConfiguration'." 

79) 

80_BPO_LOCK_TIME_MESSAGE = ( 

81 "'IAMConfiguration.bucket_policy_only_lock_time' is deprecated. " 

82 "Instead, use 'IAMConfiguration.uniform_bucket_level_access_lock_time'." 

83) 

84_LOCATION_SETTER_MESSAGE = ( 

85 "Assignment to 'Bucket.location' is deprecated, as it is only " 

86 "valid before the bucket is created. Instead, pass the location " 

87 "to `Bucket.create`." 

88) 

89_FROM_STRING_MESSAGE = ( 

90 "Bucket.from_string() is deprecated. " "Use Bucket.from_uri() instead." 

91) 

92_IP_FILTER_PROPERTY = "ipFilter" 

93 

94 

95def _blobs_page_start(iterator, page, response): 

96 """Grab prefixes after a :class:`~google.cloud.iterator.Page` started. 

97 

98 :type iterator: :class:`~google.api_core.page_iterator.Iterator` 

99 :param iterator: The iterator that is currently in use. 

100 

101 :type page: :class:`~google.cloud.api.core.page_iterator.Page` 

102 :param page: The page that was just created. 

103 

104 :type response: dict 

105 :param response: The JSON API response for a page of blobs. 

106 """ 

107 page.prefixes = tuple(response.get("prefixes", ())) 

108 iterator.prefixes.update(page.prefixes) 

109 

110 

111def _item_to_blob(iterator, item): 

112 """Convert a JSON blob to the native object. 

113 

114 .. note:: 

115 

116 This assumes that the ``bucket`` attribute has been 

117 added to the iterator after being created. 

118 

119 :type iterator: :class:`~google.api_core.page_iterator.Iterator` 

120 :param iterator: The iterator that has retrieved the item. 

121 

122 :type item: dict 

123 :param item: An item to be converted to a blob. 

124 

125 :rtype: :class:`.Blob` 

126 :returns: The next blob in the page. 

127 """ 

128 name = item.get("name") 

129 blob = Blob(name, bucket=iterator.bucket) 

130 blob._set_properties(item) 

131 return blob 

132 

133 

134def _item_to_notification(iterator, item): 

135 """Convert a JSON blob to the native object. 

136 

137 .. note:: 

138 

139 This assumes that the ``bucket`` attribute has been 

140 added to the iterator after being created. 

141 

142 :type iterator: :class:`~google.api_core.page_iterator.Iterator` 

143 :param iterator: The iterator that has retrieved the item. 

144 

145 :type item: dict 

146 :param item: An item to be converted to a blob. 

147 

148 :rtype: :class:`.BucketNotification` 

149 :returns: The next notification being iterated. 

150 """ 

151 return BucketNotification.from_api_repr(item, bucket=iterator.bucket) 

152 

153 

154class LifecycleRuleConditions(dict): 

155 """Map a single lifecycle rule for a bucket. 

156 

157 See: https://cloud.google.com/storage/docs/lifecycle 

158 

159 :type age: int 

160 :param age: (Optional) Apply rule action to items whose age, in days, 

161 exceeds this value. 

162 

163 :type created_before: datetime.date 

164 :param created_before: (Optional) Apply rule action to items created 

165 before this date. 

166 

167 :type is_live: bool 

168 :param is_live: (Optional) If true, apply rule action to non-versioned 

169 items, or to items with no newer versions. If false, apply 

170 rule action to versioned items with at least one newer 

171 version. 

172 

173 :type matches_prefix: list(str) 

174 :param matches_prefix: (Optional) Apply rule action to items which 

175 any prefix matches the beginning of the item name. 

176 

177 :type matches_storage_class: list(str), one or more of 

178 :attr:`Bucket.STORAGE_CLASSES`. 

179 :param matches_storage_class: (Optional) Apply rule action to items 

180 whose storage class matches this value. 

181 

182 :type matches_suffix: list(str) 

183 :param matches_suffix: (Optional) Apply rule action to items which 

184 any suffix matches the end of the item name. 

185 

186 :type number_of_newer_versions: int 

187 :param number_of_newer_versions: (Optional) Apply rule action to versioned 

188 items having N newer versions. 

189 

190 :type days_since_custom_time: int 

191 :param days_since_custom_time: (Optional) Apply rule action to items whose number of days 

192 elapsed since the custom timestamp. This condition is relevant 

193 only for versioned objects. The value of the field must be a non 

194 negative integer. If it's zero, the object version will become 

195 eligible for lifecycle action as soon as it becomes custom. 

196 

197 :type custom_time_before: :class:`datetime.date` 

198 :param custom_time_before: (Optional) Date object parsed from RFC3339 valid date, apply rule action 

199 to items whose custom time is before this date. This condition is relevant 

200 only for versioned objects, e.g., 2019-03-16. 

201 

202 :type days_since_noncurrent_time: int 

203 :param days_since_noncurrent_time: (Optional) Apply rule action to items whose number of days 

204 elapsed since the non current timestamp. This condition 

205 is relevant only for versioned objects. The value of the field 

206 must be a non negative integer. If it's zero, the object version 

207 will become eligible for lifecycle action as soon as it becomes 

208 non current. 

209 

210 :type noncurrent_time_before: :class:`datetime.date` 

211 :param noncurrent_time_before: (Optional) Date object parsed from RFC3339 valid date, apply 

212 rule action to items whose non current time is before this date. 

213 This condition is relevant only for versioned objects, e.g, 2019-03-16. 

214 

215 :raises ValueError: if no arguments are passed. 

216 """ 

217 

218 def __init__( 

219 self, 

220 age=None, 

221 created_before=None, 

222 is_live=None, 

223 matches_storage_class=None, 

224 number_of_newer_versions=None, 

225 days_since_custom_time=None, 

226 custom_time_before=None, 

227 days_since_noncurrent_time=None, 

228 noncurrent_time_before=None, 

229 matches_prefix=None, 

230 matches_suffix=None, 

231 _factory=False, 

232 ): 

233 conditions = {} 

234 

235 if age is not None: 

236 conditions["age"] = age 

237 

238 if created_before is not None: 

239 conditions["createdBefore"] = created_before.isoformat() 

240 

241 if is_live is not None: 

242 conditions["isLive"] = is_live 

243 

244 if matches_storage_class is not None: 

245 conditions["matchesStorageClass"] = matches_storage_class 

246 

247 if number_of_newer_versions is not None: 

248 conditions["numNewerVersions"] = number_of_newer_versions 

249 

250 if days_since_custom_time is not None: 

251 conditions["daysSinceCustomTime"] = days_since_custom_time 

252 

253 if custom_time_before is not None: 

254 conditions["customTimeBefore"] = custom_time_before.isoformat() 

255 

256 if days_since_noncurrent_time is not None: 

257 conditions["daysSinceNoncurrentTime"] = days_since_noncurrent_time 

258 

259 if noncurrent_time_before is not None: 

260 conditions["noncurrentTimeBefore"] = noncurrent_time_before.isoformat() 

261 

262 if matches_prefix is not None: 

263 conditions["matchesPrefix"] = matches_prefix 

264 

265 if matches_suffix is not None: 

266 conditions["matchesSuffix"] = matches_suffix 

267 

268 if not _factory and not conditions: 

269 raise ValueError("Supply at least one condition") 

270 

271 super(LifecycleRuleConditions, self).__init__(conditions) 

272 

273 @classmethod 

274 def from_api_repr(cls, resource): 

275 """Factory: construct instance from resource. 

276 

277 :type resource: dict 

278 :param resource: mapping as returned from API call. 

279 

280 :rtype: :class:`LifecycleRuleConditions` 

281 :returns: Instance created from resource. 

282 """ 

283 instance = cls(_factory=True) 

284 instance.update(resource) 

285 return instance 

286 

287 @property 

288 def age(self): 

289 """Conditon's age value.""" 

290 return self.get("age") 

291 

292 @property 

293 def created_before(self): 

294 """Conditon's created_before value.""" 

295 before = self.get("createdBefore") 

296 if before is not None: 

297 return datetime_helpers.from_iso8601_date(before) 

298 

299 @property 

300 def is_live(self): 

301 """Conditon's 'is_live' value.""" 

302 return self.get("isLive") 

303 

304 @property 

305 def matches_prefix(self): 

306 """Conditon's 'matches_prefix' value.""" 

307 return self.get("matchesPrefix") 

308 

309 @property 

310 def matches_storage_class(self): 

311 """Conditon's 'matches_storage_class' value.""" 

312 return self.get("matchesStorageClass") 

313 

314 @property 

315 def matches_suffix(self): 

316 """Conditon's 'matches_suffix' value.""" 

317 return self.get("matchesSuffix") 

318 

319 @property 

320 def number_of_newer_versions(self): 

321 """Conditon's 'number_of_newer_versions' value.""" 

322 return self.get("numNewerVersions") 

323 

324 @property 

325 def days_since_custom_time(self): 

326 """Conditon's 'days_since_custom_time' value.""" 

327 return self.get("daysSinceCustomTime") 

328 

329 @property 

330 def custom_time_before(self): 

331 """Conditon's 'custom_time_before' value.""" 

332 before = self.get("customTimeBefore") 

333 if before is not None: 

334 return datetime_helpers.from_iso8601_date(before) 

335 

336 @property 

337 def days_since_noncurrent_time(self): 

338 """Conditon's 'days_since_noncurrent_time' value.""" 

339 return self.get("daysSinceNoncurrentTime") 

340 

341 @property 

342 def noncurrent_time_before(self): 

343 """Conditon's 'noncurrent_time_before' value.""" 

344 before = self.get("noncurrentTimeBefore") 

345 if before is not None: 

346 return datetime_helpers.from_iso8601_date(before) 

347 

348 

349class LifecycleRuleDelete(dict): 

350 """Map a lifecycle rule deleting matching items. 

351 

352 :type kw: dict 

353 :params kw: arguments passed to :class:`LifecycleRuleConditions`. 

354 """ 

355 

356 def __init__(self, **kw): 

357 conditions = LifecycleRuleConditions(**kw) 

358 rule = {"action": {"type": "Delete"}, "condition": dict(conditions)} 

359 super().__init__(rule) 

360 

361 @classmethod 

362 def from_api_repr(cls, resource): 

363 """Factory: construct instance from resource. 

364 

365 :type resource: dict 

366 :param resource: mapping as returned from API call. 

367 

368 :rtype: :class:`LifecycleRuleDelete` 

369 :returns: Instance created from resource. 

370 """ 

371 instance = cls(_factory=True) 

372 instance.update(resource) 

373 return instance 

374 

375 

376class LifecycleRuleSetStorageClass(dict): 

377 """Map a lifecycle rule updating storage class of matching items. 

378 

379 :type storage_class: str, one of :attr:`Bucket.STORAGE_CLASSES`. 

380 :param storage_class: new storage class to assign to matching items. 

381 

382 :type kw: dict 

383 :params kw: arguments passed to :class:`LifecycleRuleConditions`. 

384 """ 

385 

386 def __init__(self, storage_class, **kw): 

387 conditions = LifecycleRuleConditions(**kw) 

388 rule = { 

389 "action": { 

390 "type": "SetStorageClass", 

391 "storageClass": storage_class, 

392 }, 

393 "condition": dict(conditions), 

394 } 

395 super().__init__(rule) 

396 

397 @classmethod 

398 def from_api_repr(cls, resource): 

399 """Factory: construct instance from resource. 

400 

401 :type resource: dict 

402 :param resource: mapping as returned from API call. 

403 

404 :rtype: :class:`LifecycleRuleSetStorageClass` 

405 :returns: Instance created from resource. 

406 """ 

407 action = resource["action"] 

408 instance = cls(action["storageClass"], _factory=True) 

409 instance.update(resource) 

410 return instance 

411 

412 

413class LifecycleRuleAbortIncompleteMultipartUpload(dict): 

414 """Map a rule aborting incomplete multipart uploads of matching items. 

415 

416 The "age" lifecycle condition is the only supported condition for this rule. 

417 

418 :type kw: dict 

419 :params kw: arguments passed to :class:`LifecycleRuleConditions`. 

420 """ 

421 

422 def __init__(self, **kw): 

423 conditions = LifecycleRuleConditions(**kw) 

424 rule = { 

425 "action": {"type": "AbortIncompleteMultipartUpload"}, 

426 "condition": dict(conditions), 

427 } 

428 super().__init__(rule) 

429 

430 @classmethod 

431 def from_api_repr(cls, resource): 

432 """Factory: construct instance from resource. 

433 

434 :type resource: dict 

435 :param resource: mapping as returned from API call. 

436 

437 :rtype: :class:`LifecycleRuleAbortIncompleteMultipartUpload` 

438 :returns: Instance created from resource. 

439 """ 

440 instance = cls(_factory=True) 

441 instance.update(resource) 

442 return instance 

443 

444 

445_default = object() 

446 

447 

448class IAMConfiguration(dict): 

449 """Map a bucket's IAM configuration. 

450 

451 :type bucket: :class:`Bucket` 

452 :params bucket: Bucket for which this instance is the policy. 

453 

454 :type public_access_prevention: str 

455 :params public_access_prevention: 

456 (Optional) Whether the public access prevention policy is 'inherited' (default) or 'enforced' 

457 See: https://cloud.google.com/storage/docs/public-access-prevention 

458 

459 :type uniform_bucket_level_access_enabled: bool 

460 :params bucket_policy_only_enabled: 

461 (Optional) Whether the IAM-only policy is enabled for the bucket. 

462 

463 :type uniform_bucket_level_access_locked_time: :class:`datetime.datetime` 

464 :params uniform_bucket_level_locked_time: 

465 (Optional) When the bucket's IAM-only policy was enabled. 

466 This value should normally only be set by the back-end API. 

467 

468 :type bucket_policy_only_enabled: bool 

469 :params bucket_policy_only_enabled: 

470 Deprecated alias for :data:`uniform_bucket_level_access_enabled`. 

471 

472 :type bucket_policy_only_locked_time: :class:`datetime.datetime` 

473 :params bucket_policy_only_locked_time: 

474 Deprecated alias for :data:`uniform_bucket_level_access_locked_time`. 

475 """ 

476 

477 def __init__( 

478 self, 

479 bucket, 

480 public_access_prevention=_default, 

481 uniform_bucket_level_access_enabled=_default, 

482 uniform_bucket_level_access_locked_time=_default, 

483 bucket_policy_only_enabled=_default, 

484 bucket_policy_only_locked_time=_default, 

485 ): 

486 if bucket_policy_only_enabled is not _default: 

487 if uniform_bucket_level_access_enabled is not _default: 

488 raise ValueError(_UBLA_BPO_ENABLED_MESSAGE) 

489 

490 warnings.warn(_BPO_ENABLED_MESSAGE, DeprecationWarning, stacklevel=2) 

491 uniform_bucket_level_access_enabled = bucket_policy_only_enabled 

492 

493 if bucket_policy_only_locked_time is not _default: 

494 if uniform_bucket_level_access_locked_time is not _default: 

495 raise ValueError(_UBLA_BPO_LOCK_TIME_MESSAGE) 

496 

497 warnings.warn(_BPO_LOCK_TIME_MESSAGE, DeprecationWarning, stacklevel=2) 

498 uniform_bucket_level_access_locked_time = bucket_policy_only_locked_time 

499 

500 if uniform_bucket_level_access_enabled is _default: 

501 uniform_bucket_level_access_enabled = False 

502 

503 if public_access_prevention is _default: 

504 public_access_prevention = PUBLIC_ACCESS_PREVENTION_INHERITED 

505 

506 data = { 

507 "uniformBucketLevelAccess": { 

508 "enabled": uniform_bucket_level_access_enabled 

509 }, 

510 "publicAccessPrevention": public_access_prevention, 

511 } 

512 if uniform_bucket_level_access_locked_time is not _default: 

513 data["uniformBucketLevelAccess"]["lockedTime"] = _datetime_to_rfc3339( 

514 uniform_bucket_level_access_locked_time 

515 ) 

516 super(IAMConfiguration, self).__init__(data) 

517 self._bucket = bucket 

518 

519 @classmethod 

520 def from_api_repr(cls, resource, bucket): 

521 """Factory: construct instance from resource. 

522 

523 :type bucket: :class:`Bucket` 

524 :params bucket: Bucket for which this instance is the policy. 

525 

526 :type resource: dict 

527 :param resource: mapping as returned from API call. 

528 

529 :rtype: :class:`IAMConfiguration` 

530 :returns: Instance created from resource. 

531 """ 

532 instance = cls(bucket) 

533 instance.update(resource) 

534 return instance 

535 

536 @property 

537 def bucket(self): 

538 """Bucket for which this instance is the policy. 

539 

540 :rtype: :class:`Bucket` 

541 :returns: the instance's bucket. 

542 """ 

543 return self._bucket 

544 

545 @property 

546 def public_access_prevention(self): 

547 """Setting for public access prevention policy. Options are 'inherited' (default) or 'enforced'. 

548 

549 See: https://cloud.google.com/storage/docs/public-access-prevention 

550 

551 :rtype: string 

552 :returns: the public access prevention status, either 'enforced' or 'inherited'. 

553 """ 

554 return self["publicAccessPrevention"] 

555 

556 @public_access_prevention.setter 

557 def public_access_prevention(self, value): 

558 self["publicAccessPrevention"] = value 

559 self.bucket._patch_property("iamConfiguration", self) 

560 

561 @property 

562 def uniform_bucket_level_access_enabled(self): 

563 """If set, access checks only use bucket-level IAM policies or above. 

564 

565 :rtype: bool 

566 :returns: whether the bucket is configured to allow only IAM. 

567 """ 

568 ubla = self.get("uniformBucketLevelAccess", {}) 

569 return ubla.get("enabled", False) 

570 

571 @uniform_bucket_level_access_enabled.setter 

572 def uniform_bucket_level_access_enabled(self, value): 

573 ubla = self.setdefault("uniformBucketLevelAccess", {}) 

574 ubla["enabled"] = bool(value) 

575 self.bucket._patch_property("iamConfiguration", self) 

576 

577 @property 

578 def uniform_bucket_level_access_locked_time(self): 

579 """Deadline for changing :attr:`uniform_bucket_level_access_enabled` from true to false. 

580 

581 If the bucket's :attr:`uniform_bucket_level_access_enabled` is true, this property 

582 is time time after which that setting becomes immutable. 

583 

584 If the bucket's :attr:`uniform_bucket_level_access_enabled` is false, this property 

585 is ``None``. 

586 

587 :rtype: Union[:class:`datetime.datetime`, None] 

588 :returns: (readonly) Time after which :attr:`uniform_bucket_level_access_enabled` will 

589 be frozen as true. 

590 """ 

591 ubla = self.get("uniformBucketLevelAccess", {}) 

592 stamp = ubla.get("lockedTime") 

593 if stamp is not None: 

594 stamp = _rfc3339_nanos_to_datetime(stamp) 

595 return stamp 

596 

597 @property 

598 def bucket_policy_only_enabled(self): 

599 """Deprecated alias for :attr:`uniform_bucket_level_access_enabled`. 

600 

601 :rtype: bool 

602 :returns: whether the bucket is configured to allow only IAM. 

603 """ 

604 return self.uniform_bucket_level_access_enabled 

605 

606 @bucket_policy_only_enabled.setter 

607 def bucket_policy_only_enabled(self, value): 

608 warnings.warn(_BPO_ENABLED_MESSAGE, DeprecationWarning, stacklevel=2) 

609 self.uniform_bucket_level_access_enabled = value 

610 

611 @property 

612 def bucket_policy_only_locked_time(self): 

613 """Deprecated alias for :attr:`uniform_bucket_level_access_locked_time`. 

614 

615 :rtype: Union[:class:`datetime.datetime`, None] 

616 :returns: 

617 (readonly) Time after which :attr:`bucket_policy_only_enabled` will 

618 be frozen as true. 

619 """ 

620 return self.uniform_bucket_level_access_locked_time 

621 

622 

623class Bucket(_PropertyMixin): 

624 """A class representing a Bucket on Cloud Storage. 

625 

626 :type client: :class:`google.cloud.storage.client.Client` 

627 :param client: A client which holds credentials and project configuration 

628 for the bucket (which requires a project). 

629 

630 :type name: str 

631 :param name: The name of the bucket. Bucket names must start and end with a 

632 number or letter. 

633 

634 :type user_project: str 

635 :param user_project: (Optional) the project ID to be billed for API 

636 requests made via this instance. 

637 

638 :type generation: int 

639 :param generation: (Optional) If present, selects a specific revision of 

640 this bucket. 

641 """ 

642 

643 _MAX_OBJECTS_FOR_ITERATION = 256 

644 """Maximum number of existing objects allowed in iteration. 

645 

646 This is used in Bucket.delete() and Bucket.make_public(). 

647 """ 

648 

649 STORAGE_CLASSES = ( 

650 STANDARD_STORAGE_CLASS, 

651 NEARLINE_STORAGE_CLASS, 

652 COLDLINE_STORAGE_CLASS, 

653 ARCHIVE_STORAGE_CLASS, 

654 MULTI_REGIONAL_LEGACY_STORAGE_CLASS, # legacy 

655 REGIONAL_LEGACY_STORAGE_CLASS, # legacy 

656 DURABLE_REDUCED_AVAILABILITY_LEGACY_STORAGE_CLASS, # legacy 

657 ) 

658 """Allowed values for :attr:`storage_class`. 

659 

660 Default value is :attr:`STANDARD_STORAGE_CLASS`. 

661 

662 See 

663 https://cloud.google.com/storage/docs/json_api/v1/buckets#storageClass 

664 https://cloud.google.com/storage/docs/storage-classes 

665 """ 

666 

667 _LOCATION_TYPES = ( 

668 MULTI_REGION_LOCATION_TYPE, 

669 REGION_LOCATION_TYPE, 

670 DUAL_REGION_LOCATION_TYPE, 

671 ) 

672 """Allowed values for :attr:`location_type`.""" 

673 

674 def __init__(self, client, name=None, user_project=None, generation=None): 

675 """ 

676 property :attr:`name` 

677 Get the bucket's name. 

678 """ 

679 name = _validate_name(name) 

680 super(Bucket, self).__init__(name=name) 

681 self._client = client 

682 self._acl = BucketACL(self) 

683 self._default_object_acl = DefaultObjectACL(self) 

684 self._label_removals = set() 

685 self._user_project = user_project 

686 

687 if generation is not None: 

688 self._properties["generation"] = generation 

689 

690 def __repr__(self): 

691 return f"<Bucket: {self.name}>" 

692 

693 @property 

694 def client(self): 

695 """The client bound to this bucket.""" 

696 return self._client 

697 

698 def _set_properties(self, value): 

699 """Set the properties for the current object. 

700 

701 :type value: dict or :class:`google.cloud.storage.batch._FutureDict` 

702 :param value: The properties to be set. 

703 """ 

704 self._label_removals.clear() 

705 return super(Bucket, self)._set_properties(value) 

706 

707 @property 

708 def rpo(self): 

709 """Get the RPO (Recovery Point Objective) of this bucket 

710 

711 See: https://cloud.google.com/storage/docs/managing-turbo-replication 

712 

713 "ASYNC_TURBO" or "DEFAULT" 

714 :rtype: str 

715 """ 

716 return self._properties.get("rpo") 

717 

718 @rpo.setter 

719 def rpo(self, value): 

720 """ 

721 Set the RPO (Recovery Point Objective) of this bucket. 

722 

723 See: https://cloud.google.com/storage/docs/managing-turbo-replication 

724 

725 :type value: str 

726 :param value: "ASYNC_TURBO" or "DEFAULT" 

727 """ 

728 self._patch_property("rpo", value) 

729 

730 @property 

731 def user_project(self): 

732 """Project ID to be billed for API requests made via this bucket. 

733 

734 If unset, API requests are billed to the bucket owner. 

735 

736 A user project is required for all operations on Requester Pays buckets. 

737 

738 See https://cloud.google.com/storage/docs/requester-pays#requirements for details. 

739 

740 :rtype: str 

741 """ 

742 return self._user_project 

743 

744 @property 

745 def generation(self): 

746 """Retrieve the generation for the bucket. 

747 

748 :rtype: int or ``NoneType`` 

749 :returns: The generation of the bucket or ``None`` if the bucket's 

750 resource has not been loaded from the server. 

751 """ 

752 generation = self._properties.get("generation") 

753 if generation is not None: 

754 return int(generation) 

755 

756 @property 

757 def soft_delete_time(self): 

758 """If this bucket has been soft-deleted, returns the time at which it became soft-deleted. 

759 

760 :rtype: :class:`datetime.datetime` or ``NoneType`` 

761 :returns: 

762 (readonly) The time that the bucket became soft-deleted. 

763 Note this property is only set for soft-deleted buckets. 

764 """ 

765 soft_delete_time = self._properties.get("softDeleteTime") 

766 if soft_delete_time is not None: 

767 return _rfc3339_nanos_to_datetime(soft_delete_time) 

768 

769 @property 

770 def hard_delete_time(self): 

771 """If this bucket has been soft-deleted, returns the time at which it will be permanently deleted. 

772 

773 :rtype: :class:`datetime.datetime` or ``NoneType`` 

774 :returns: 

775 (readonly) The time that the bucket will be permanently deleted. 

776 Note this property is only set for soft-deleted buckets. 

777 """ 

778 hard_delete_time = self._properties.get("hardDeleteTime") 

779 if hard_delete_time is not None: 

780 return _rfc3339_nanos_to_datetime(hard_delete_time) 

781 

782 @property 

783 def _query_params(self): 

784 """Default query parameters.""" 

785 params = super()._query_params 

786 return params 

787 

788 @classmethod 

789 def from_uri(cls, uri, client=None): 

790 """Get a constructor for bucket object by URI. 

791 

792 .. code-block:: python 

793 

794 from google.cloud import storage 

795 from google.cloud.storage.bucket import Bucket 

796 client = storage.Client() 

797 bucket = Bucket.from_uri("gs://bucket", client=client) 

798 

799 :type uri: str 

800 :param uri: The bucket uri pass to get bucket object. 

801 

802 :type client: :class:`~google.cloud.storage.client.Client` or 

803 ``NoneType`` 

804 :param client: (Optional) The client to use. Application code should 

805 *always* pass ``client``. 

806 

807 :rtype: :class:`google.cloud.storage.bucket.Bucket` 

808 :returns: The bucket object created. 

809 """ 

810 scheme, netloc, path, query, frag = urlsplit(uri) 

811 

812 if scheme != "gs": 

813 raise ValueError("URI scheme must be gs") 

814 

815 return cls(client, name=netloc) 

816 

817 @classmethod 

818 def from_string(cls, uri, client=None): 

819 """Get a constructor for bucket object by URI. 

820 

821 .. note:: 

822 Deprecated alias for :meth:`from_uri`. 

823 

824 .. code-block:: python 

825 

826 from google.cloud import storage 

827 from google.cloud.storage.bucket import Bucket 

828 client = storage.Client() 

829 bucket = Bucket.from_string("gs://bucket", client=client) 

830 

831 :type uri: str 

832 :param uri: The bucket uri pass to get bucket object. 

833 

834 :type client: :class:`~google.cloud.storage.client.Client` or 

835 ``NoneType`` 

836 :param client: (Optional) The client to use. Application code should 

837 *always* pass ``client``. 

838 

839 :rtype: :class:`google.cloud.storage.bucket.Bucket` 

840 :returns: The bucket object created. 

841 """ 

842 warnings.warn(_FROM_STRING_MESSAGE, PendingDeprecationWarning, stacklevel=2) 

843 return Bucket.from_uri(uri=uri, client=client) 

844 

845 def blob( 

846 self, 

847 blob_name, 

848 chunk_size=None, 

849 encryption_key=None, 

850 kms_key_name=None, 

851 generation=None, 

852 ): 

853 """Factory constructor for blob object. 

854 

855 .. note:: 

856 This will not make an HTTP request; it simply instantiates 

857 a blob object owned by this bucket. 

858 

859 :type blob_name: str 

860 :param blob_name: The name of the blob to be instantiated. 

861 

862 :type chunk_size: int 

863 :param chunk_size: The size of a chunk of data whenever iterating 

864 (in bytes). This must be a multiple of 256 KB per 

865 the API specification. 

866 

867 :type encryption_key: bytes 

868 :param encryption_key: 

869 (Optional) 32 byte encryption key for customer-supplied encryption. 

870 

871 :type kms_key_name: str 

872 :param kms_key_name: 

873 (Optional) Resource name of KMS key used to encrypt blob's content. 

874 

875 :type generation: long 

876 :param generation: (Optional) If present, selects a specific revision of 

877 this object. 

878 

879 :type crc32c_checksum: str 

880 :param crc32c_checksum: 

881 (Optional) If set, the CRC32C checksum of the blob's content. 

882 CRC32c checksum, as described in RFC 4960, Appendix B; encoded using 

883 base64 in big-endian byte order. See 

884 Apenndix B: https://datatracker.ietf.org/doc/html/rfc4960#appendix-B 

885 base64: https://datatracker.ietf.org/doc/html/rfc4648#section-4 

886 

887 :rtype: :class:`google.cloud.storage.blob.Blob` 

888 :returns: The blob object created. 

889 """ 

890 return Blob( 

891 name=blob_name, 

892 bucket=self, 

893 chunk_size=chunk_size, 

894 encryption_key=encryption_key, 

895 kms_key_name=kms_key_name, 

896 generation=generation, 

897 ) 

898 

899 def notification( 

900 self, 

901 topic_name=None, 

902 topic_project=None, 

903 custom_attributes=None, 

904 event_types=None, 

905 blob_name_prefix=None, 

906 payload_format=NONE_PAYLOAD_FORMAT, 

907 notification_id=None, 

908 ): 

909 """Factory: create a notification resource for the bucket. 

910 

911 See: :class:`.BucketNotification` for parameters. 

912 

913 :rtype: :class:`.BucketNotification` 

914 """ 

915 return BucketNotification( 

916 self, 

917 topic_name=topic_name, 

918 topic_project=topic_project, 

919 custom_attributes=custom_attributes, 

920 event_types=event_types, 

921 blob_name_prefix=blob_name_prefix, 

922 payload_format=payload_format, 

923 notification_id=notification_id, 

924 ) 

925 

926 def exists( 

927 self, 

928 client=None, 

929 timeout=_DEFAULT_TIMEOUT, 

930 if_etag_match=None, 

931 if_etag_not_match=None, 

932 if_metageneration_match=None, 

933 if_metageneration_not_match=None, 

934 retry=DEFAULT_RETRY, 

935 ): 

936 """Determines whether or not this bucket exists. 

937 

938 If :attr:`user_project` is set, bills the API request to that project. 

939 

940 :type client: :class:`~google.cloud.storage.client.Client` or 

941 ``NoneType`` 

942 :param client: (Optional) The client to use. If not passed, falls back 

943 to the ``client`` stored on the current bucket. 

944 

945 :type timeout: float or tuple 

946 :param timeout: 

947 (Optional) The amount of time, in seconds, to wait 

948 for the server response. See: :ref:`configuring_timeouts` 

949 

950 :type if_etag_match: Union[str, Set[str]] 

951 :param if_etag_match: (Optional) Make the operation conditional on whether the 

952 bucket's current ETag matches the given value. 

953 

954 :type if_etag_not_match: Union[str, Set[str]]) 

955 :param if_etag_not_match: (Optional) Make the operation conditional on whether the 

956 bucket's current ETag does not match the given value. 

957 

958 :type if_metageneration_match: long 

959 :param if_metageneration_match: (Optional) Make the operation conditional on whether the 

960 bucket's current metageneration matches the given value. 

961 

962 :type if_metageneration_not_match: long 

963 :param if_metageneration_not_match: (Optional) Make the operation conditional on whether the 

964 bucket's current metageneration does not match the given value. 

965 

966 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

967 :param retry: 

968 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

969 

970 :rtype: bool 

971 :returns: True if the bucket exists in Cloud Storage. 

972 """ 

973 with create_trace_span(name="Storage.Bucket.exists"): 

974 client = self._require_client(client) 

975 # We only need the status code (200 or not) so we seek to 

976 # minimize the returned payload. 

977 query_params = {"fields": "name"} 

978 

979 if self.user_project is not None: 

980 query_params["userProject"] = self.user_project 

981 

982 _add_generation_match_parameters( 

983 query_params, 

984 if_metageneration_match=if_metageneration_match, 

985 if_metageneration_not_match=if_metageneration_not_match, 

986 ) 

987 

988 headers = {} 

989 _add_etag_match_headers( 

990 headers, 

991 if_etag_match=if_etag_match, 

992 if_etag_not_match=if_etag_not_match, 

993 ) 

994 

995 try: 

996 # We intentionally pass `_target_object=None` since fields=name 

997 # would limit the local properties. 

998 client._get_resource( 

999 self.path, 

1000 query_params=query_params, 

1001 headers=headers, 

1002 timeout=timeout, 

1003 retry=retry, 

1004 _target_object=None, 

1005 ) 

1006 except NotFound: 

1007 # NOTE: This will not fail immediately in a batch. However, when 

1008 # Batch.finish() is called, the resulting `NotFound` will be 

1009 # raised. 

1010 return False 

1011 return True 

1012 

1013 def create( 

1014 self, 

1015 client=None, 

1016 project=None, 

1017 location=None, 

1018 predefined_acl=None, 

1019 predefined_default_object_acl=None, 

1020 enable_object_retention=False, 

1021 timeout=_DEFAULT_TIMEOUT, 

1022 retry=DEFAULT_RETRY, 

1023 ): 

1024 """Creates current bucket. 

1025 

1026 If the bucket already exists, will raise 

1027 :class:`google.cloud.exceptions.Conflict`. 

1028 

1029 This implements "storage.buckets.insert". 

1030 

1031 If :attr:`user_project` is set, bills the API request to that project. 

1032 

1033 :type client: :class:`~google.cloud.storage.client.Client` or 

1034 ``NoneType`` 

1035 :param client: (Optional) The client to use. If not passed, falls back 

1036 to the ``client`` stored on the current bucket. 

1037 

1038 :type project: str 

1039 :param project: (Optional) The project under which the bucket is to 

1040 be created. If not passed, uses the project set on 

1041 the client. 

1042 :raises ValueError: if ``project`` is None and client's 

1043 :attr:`project` is also None. 

1044 

1045 :type location: str 

1046 :param location: (Optional) The location of the bucket. If not passed, 

1047 the default location, US, will be used. See 

1048 https://cloud.google.com/storage/docs/bucket-locations 

1049 

1050 :type predefined_acl: str 

1051 :param predefined_acl: 

1052 (Optional) Name of predefined ACL to apply to bucket. See: 

1053 https://cloud.google.com/storage/docs/access-control/lists#predefined-acl 

1054 

1055 :type predefined_default_object_acl: str 

1056 :param predefined_default_object_acl: 

1057 (Optional) Name of predefined ACL to apply to bucket's objects. See: 

1058 https://cloud.google.com/storage/docs/access-control/lists#predefined-acl 

1059 

1060 :type enable_object_retention: bool 

1061 :param enable_object_retention: 

1062 (Optional) Whether object retention should be enabled on this bucket. See: 

1063 https://cloud.google.com/storage/docs/object-lock 

1064 

1065 :type timeout: float or tuple 

1066 :param timeout: 

1067 (Optional) The amount of time, in seconds, to wait 

1068 for the server response. See: :ref:`configuring_timeouts` 

1069 

1070 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1071 :param retry: 

1072 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

1073 """ 

1074 with create_trace_span(name="Storage.Bucket.create"): 

1075 client = self._require_client(client) 

1076 client.create_bucket( 

1077 bucket_or_name=self, 

1078 project=project, 

1079 user_project=self.user_project, 

1080 location=location, 

1081 predefined_acl=predefined_acl, 

1082 predefined_default_object_acl=predefined_default_object_acl, 

1083 enable_object_retention=enable_object_retention, 

1084 timeout=timeout, 

1085 retry=retry, 

1086 ) 

1087 

1088 def update( 

1089 self, 

1090 client=None, 

1091 timeout=_DEFAULT_TIMEOUT, 

1092 if_metageneration_match=None, 

1093 if_metageneration_not_match=None, 

1094 retry=DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED, 

1095 ): 

1096 """Sends all properties in a PUT request. 

1097 

1098 Updates the ``_properties`` with the response from the backend. 

1099 

1100 If :attr:`user_project` is set, bills the API request to that project. 

1101 

1102 :type client: :class:`~google.cloud.storage.client.Client` or 

1103 ``NoneType`` 

1104 :param client: the client to use. If not passed, falls back to the 

1105 ``client`` stored on the current object. 

1106 

1107 :type timeout: float or tuple 

1108 :param timeout: 

1109 (Optional) The amount of time, in seconds, to wait 

1110 for the server response. See: :ref:`configuring_timeouts` 

1111 

1112 :type if_metageneration_match: long 

1113 :param if_metageneration_match: (Optional) Make the operation conditional on whether the 

1114 blob's current metageneration matches the given value. 

1115 

1116 :type if_metageneration_not_match: long 

1117 :param if_metageneration_not_match: (Optional) Make the operation conditional on whether the 

1118 blob's current metageneration does not match the given value. 

1119 

1120 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1121 :param retry: 

1122 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

1123 """ 

1124 with create_trace_span(name="Storage.Bucket.update"): 

1125 super(Bucket, self).update( 

1126 client=client, 

1127 timeout=timeout, 

1128 if_metageneration_match=if_metageneration_match, 

1129 if_metageneration_not_match=if_metageneration_not_match, 

1130 retry=retry, 

1131 ) 

1132 

1133 def reload( 

1134 self, 

1135 client=None, 

1136 projection="noAcl", 

1137 timeout=_DEFAULT_TIMEOUT, 

1138 if_etag_match=None, 

1139 if_etag_not_match=None, 

1140 if_metageneration_match=None, 

1141 if_metageneration_not_match=None, 

1142 retry=DEFAULT_RETRY, 

1143 soft_deleted=None, 

1144 ): 

1145 """Reload properties from Cloud Storage. 

1146 

1147 If :attr:`user_project` is set, bills the API request to that project. 

1148 

1149 :type client: :class:`~google.cloud.storage.client.Client` or 

1150 ``NoneType`` 

1151 :param client: the client to use. If not passed, falls back to the 

1152 ``client`` stored on the current object. 

1153 

1154 :type projection: str 

1155 :param projection: (Optional) If used, must be 'full' or 'noAcl'. 

1156 Defaults to ``'noAcl'``. Specifies the set of 

1157 properties to return. 

1158 

1159 :type timeout: float or tuple 

1160 :param timeout: 

1161 (Optional) The amount of time, in seconds, to wait 

1162 for the server response. See: :ref:`configuring_timeouts` 

1163 

1164 :type if_etag_match: Union[str, Set[str]] 

1165 :param if_etag_match: (Optional) Make the operation conditional on whether the 

1166 bucket's current ETag matches the given value. 

1167 

1168 :type if_etag_not_match: Union[str, Set[str]]) 

1169 :param if_etag_not_match: (Optional) Make the operation conditional on whether the 

1170 bucket's current ETag does not match the given value. 

1171 

1172 :type if_metageneration_match: long 

1173 :param if_metageneration_match: (Optional) Make the operation conditional on whether the 

1174 bucket's current metageneration matches the given value. 

1175 

1176 :type if_metageneration_not_match: long 

1177 :param if_metageneration_not_match: (Optional) Make the operation conditional on whether the 

1178 bucket's current metageneration does not match the given value. 

1179 

1180 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1181 :param retry: 

1182 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

1183 

1184 :type soft_deleted: bool 

1185 :param soft_deleted: (Optional) If True, looks for a soft-deleted 

1186 bucket. Will only return the bucket metadata if the bucket exists 

1187 and is in a soft-deleted state. The bucket ``generation`` must be 

1188 set if ``soft_deleted`` is set to True. 

1189 See: https://cloud.google.com/storage/docs/soft-delete 

1190 """ 

1191 with create_trace_span(name="Storage.Bucket.reload"): 

1192 super(Bucket, self).reload( 

1193 client=client, 

1194 projection=projection, 

1195 timeout=timeout, 

1196 if_etag_match=if_etag_match, 

1197 if_etag_not_match=if_etag_not_match, 

1198 if_metageneration_match=if_metageneration_match, 

1199 if_metageneration_not_match=if_metageneration_not_match, 

1200 retry=retry, 

1201 soft_deleted=soft_deleted, 

1202 ) 

1203 

1204 def patch( 

1205 self, 

1206 client=None, 

1207 timeout=_DEFAULT_TIMEOUT, 

1208 if_metageneration_match=None, 

1209 if_metageneration_not_match=None, 

1210 retry=DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED, 

1211 ): 

1212 """Sends all changed properties in a PATCH request. 

1213 

1214 Updates the ``_properties`` with the response from the backend. 

1215 

1216 If :attr:`user_project` is set, bills the API request to that project. 

1217 

1218 :type client: :class:`~google.cloud.storage.client.Client` or 

1219 ``NoneType`` 

1220 :param client: the client to use. If not passed, falls back to the 

1221 ``client`` stored on the current object. 

1222 

1223 :type timeout: float or tuple 

1224 :param timeout: 

1225 (Optional) The amount of time, in seconds, to wait 

1226 for the server response. See: :ref:`configuring_timeouts` 

1227 

1228 :type if_metageneration_match: long 

1229 :param if_metageneration_match: (Optional) Make the operation conditional on whether the 

1230 blob's current metageneration matches the given value. 

1231 

1232 :type if_metageneration_not_match: long 

1233 :param if_metageneration_not_match: (Optional) Make the operation conditional on whether the 

1234 blob's current metageneration does not match the given value. 

1235 

1236 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1237 :param retry: 

1238 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

1239 """ 

1240 with create_trace_span(name="Storage.Bucket.patch"): 

1241 # Special case: For buckets, it is possible that labels are being 

1242 # removed; this requires special handling. 

1243 if self._label_removals: 

1244 self._changes.add("labels") 

1245 self._properties.setdefault("labels", {}) 

1246 for removed_label in self._label_removals: 

1247 self._properties["labels"][removed_label] = None 

1248 

1249 # Call the superclass method. 

1250 super(Bucket, self).patch( 

1251 client=client, 

1252 if_metageneration_match=if_metageneration_match, 

1253 if_metageneration_not_match=if_metageneration_not_match, 

1254 timeout=timeout, 

1255 retry=retry, 

1256 ) 

1257 

1258 @property 

1259 def acl(self): 

1260 """Create our ACL on demand.""" 

1261 return self._acl 

1262 

1263 @property 

1264 def default_object_acl(self): 

1265 """Create our defaultObjectACL on demand.""" 

1266 return self._default_object_acl 

1267 

1268 @staticmethod 

1269 def path_helper(bucket_name): 

1270 """Relative URL path for a bucket. 

1271 

1272 :type bucket_name: str 

1273 :param bucket_name: The bucket name in the path. 

1274 

1275 :rtype: str 

1276 :returns: The relative URL path for ``bucket_name``. 

1277 """ 

1278 return "/b/" + bucket_name 

1279 

1280 @property 

1281 def path(self): 

1282 """The URL path to this bucket.""" 

1283 if not self.name: 

1284 raise ValueError("Cannot determine path without bucket name.") 

1285 

1286 return self.path_helper(self.name) 

1287 

1288 def get_blob( 

1289 self, 

1290 blob_name, 

1291 client=None, 

1292 encryption_key=None, 

1293 generation=None, 

1294 if_etag_match=None, 

1295 if_etag_not_match=None, 

1296 if_generation_match=None, 

1297 if_generation_not_match=None, 

1298 if_metageneration_match=None, 

1299 if_metageneration_not_match=None, 

1300 timeout=_DEFAULT_TIMEOUT, 

1301 retry=DEFAULT_RETRY, 

1302 soft_deleted=None, 

1303 **kwargs, 

1304 ): 

1305 """Get a blob object by name. 

1306 

1307 See a [code sample](https://cloud.google.com/storage/docs/samples/storage-get-metadata#storage_get_metadata-python) 

1308 on how to retrieve metadata of an object. 

1309 

1310 If :attr:`user_project` is set, bills the API request to that project. 

1311 

1312 :type blob_name: str 

1313 :param blob_name: The name of the blob to retrieve. 

1314 

1315 :type client: :class:`~google.cloud.storage.client.Client` or 

1316 ``NoneType`` 

1317 :param client: (Optional) The client to use. If not passed, falls back 

1318 to the ``client`` stored on the current bucket. 

1319 

1320 :type encryption_key: bytes 

1321 :param encryption_key: 

1322 (Optional) 32 byte encryption key for customer-supplied encryption. 

1323 See 

1324 https://cloud.google.com/storage/docs/encryption#customer-supplied. 

1325 

1326 :type generation: long 

1327 :param generation: 

1328 (Optional) If present, selects a specific revision of this object. 

1329 

1330 :type if_etag_match: Union[str, Set[str]] 

1331 :param if_etag_match: 

1332 (Optional) See :ref:`using-if-etag-match` 

1333 

1334 :type if_etag_not_match: Union[str, Set[str]] 

1335 :param if_etag_not_match: 

1336 (Optional) See :ref:`using-if-etag-not-match` 

1337 

1338 :type if_generation_match: long 

1339 :param if_generation_match: 

1340 (Optional) See :ref:`using-if-generation-match` 

1341 

1342 :type if_generation_not_match: long 

1343 :param if_generation_not_match: 

1344 (Optional) See :ref:`using-if-generation-not-match` 

1345 

1346 :type if_metageneration_match: long 

1347 :param if_metageneration_match: 

1348 (Optional) See :ref:`using-if-metageneration-match` 

1349 

1350 :type if_metageneration_not_match: long 

1351 :param if_metageneration_not_match: 

1352 (Optional) See :ref:`using-if-metageneration-not-match` 

1353 

1354 :type timeout: float or tuple 

1355 :param timeout: 

1356 (Optional) The amount of time, in seconds, to wait 

1357 for the server response. See: :ref:`configuring_timeouts` 

1358 

1359 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1360 :param retry: 

1361 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

1362 

1363 :type soft_deleted: bool 

1364 :param soft_deleted: 

1365 (Optional) If True, looks for a soft-deleted object. Will only return 

1366 the object metadata if the object exists and is in a soft-deleted state. 

1367 Object ``generation`` is required if ``soft_deleted`` is set to True. 

1368 See: https://cloud.google.com/storage/docs/soft-delete 

1369 

1370 :param kwargs: Keyword arguments to pass to the 

1371 :class:`~google.cloud.storage.blob.Blob` constructor. 

1372 

1373 :rtype: :class:`google.cloud.storage.blob.Blob` or None 

1374 :returns: The blob object if it exists, otherwise None. 

1375 """ 

1376 with create_trace_span(name="Storage.Bucket.getBlob"): 

1377 blob = Blob( 

1378 bucket=self, 

1379 name=blob_name, 

1380 encryption_key=encryption_key, 

1381 generation=generation, 

1382 **kwargs, 

1383 ) 

1384 try: 

1385 # NOTE: This will not fail immediately in a batch. However, when 

1386 # Batch.finish() is called, the resulting `NotFound` will be 

1387 # raised. 

1388 blob.reload( 

1389 client=client, 

1390 timeout=timeout, 

1391 if_etag_match=if_etag_match, 

1392 if_etag_not_match=if_etag_not_match, 

1393 if_generation_match=if_generation_match, 

1394 if_generation_not_match=if_generation_not_match, 

1395 if_metageneration_match=if_metageneration_match, 

1396 if_metageneration_not_match=if_metageneration_not_match, 

1397 retry=retry, 

1398 soft_deleted=soft_deleted, 

1399 ) 

1400 except NotFound: 

1401 return None 

1402 else: 

1403 return blob 

1404 

1405 def list_blobs( 

1406 self, 

1407 max_results=None, 

1408 page_token=None, 

1409 prefix=None, 

1410 delimiter=None, 

1411 start_offset=None, 

1412 end_offset=None, 

1413 include_trailing_delimiter=None, 

1414 versions=None, 

1415 projection="noAcl", 

1416 fields=None, 

1417 client=None, 

1418 timeout=_DEFAULT_TIMEOUT, 

1419 retry=DEFAULT_RETRY, 

1420 match_glob=None, 

1421 include_folders_as_prefixes=None, 

1422 soft_deleted=None, 

1423 page_size=None, 

1424 ): 

1425 """Return an iterator used to find blobs in the bucket. 

1426 

1427 If :attr:`user_project` is set, bills the API request to that project. 

1428 

1429 :type max_results: int 

1430 :param max_results: 

1431 (Optional) The maximum number of blobs to return. 

1432 

1433 :type page_token: str 

1434 :param page_token: 

1435 (Optional) If present, return the next batch of blobs, using the 

1436 value, which must correspond to the ``nextPageToken`` value 

1437 returned in the previous response. Deprecated: use the ``pages`` 

1438 property of the returned iterator instead of manually passing the 

1439 token. 

1440 

1441 :type prefix: str 

1442 :param prefix: (Optional) Prefix used to filter blobs. 

1443 

1444 :type delimiter: str 

1445 :param delimiter: (Optional) Delimiter, used with ``prefix`` to 

1446 emulate hierarchy. 

1447 

1448 :type start_offset: str 

1449 :param start_offset: 

1450 (Optional) Filter results to objects whose names are 

1451 lexicographically equal to or after ``startOffset``. If 

1452 ``endOffset`` is also set, the objects listed will have names 

1453 between ``startOffset`` (inclusive) and ``endOffset`` (exclusive). 

1454 

1455 :type end_offset: str 

1456 :param end_offset: 

1457 (Optional) Filter results to objects whose names are 

1458 lexicographically before ``endOffset``. If ``startOffset`` is also 

1459 set, the objects listed will have names between ``startOffset`` 

1460 (inclusive) and ``endOffset`` (exclusive). 

1461 

1462 :type include_trailing_delimiter: boolean 

1463 :param include_trailing_delimiter: 

1464 (Optional) If true, objects that end in exactly one instance of 

1465 ``delimiter`` will have their metadata included in ``items`` in 

1466 addition to ``prefixes``. 

1467 

1468 :type versions: bool 

1469 :param versions: (Optional) Whether object versions should be returned 

1470 as separate blobs. 

1471 

1472 :type projection: str 

1473 :param projection: (Optional) If used, must be 'full' or 'noAcl'. 

1474 Defaults to ``'noAcl'``. Specifies the set of 

1475 properties to return. 

1476 

1477 :type fields: str 

1478 :param fields: 

1479 (Optional) Selector specifying which fields to include 

1480 in a partial response. Must be a list of fields. For 

1481 example to get a partial response with just the next 

1482 page token and the name and language of each blob returned: 

1483 ``'items(name,contentLanguage),nextPageToken'``. 

1484 See: https://cloud.google.com/storage/docs/json_api/v1/parameters#fields 

1485 

1486 :type client: :class:`~google.cloud.storage.client.Client` 

1487 :param client: (Optional) The client to use. If not passed, falls back 

1488 to the ``client`` stored on the current bucket. 

1489 

1490 :type timeout: float or tuple 

1491 :param timeout: 

1492 (Optional) The amount of time, in seconds, to wait 

1493 for the server response. See: :ref:`configuring_timeouts` 

1494 

1495 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1496 :param retry: 

1497 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

1498 

1499 :type match_glob: str 

1500 :param match_glob: 

1501 (Optional) A glob pattern used to filter results (for example, foo*bar). 

1502 The string value must be UTF-8 encoded. See: 

1503 https://cloud.google.com/storage/docs/json_api/v1/objects/list#list-object-glob 

1504 

1505 :type include_folders_as_prefixes: bool 

1506 (Optional) If true, includes Folders and Managed Folders in the set of 

1507 ``prefixes`` returned by the query. Only applicable if ``delimiter`` is set to /. 

1508 See: https://cloud.google.com/storage/docs/managed-folders 

1509 

1510 :type soft_deleted: bool 

1511 :param soft_deleted: 

1512 (Optional) If true, only soft-deleted objects will be listed as distinct results in order of increasing 

1513 generation number. This parameter can only be used successfully if the bucket has a soft delete policy. 

1514 Note ``soft_deleted`` and ``versions`` cannot be set to True simultaneously. See: 

1515 https://cloud.google.com/storage/docs/soft-delete 

1516 

1517 :type page_size: int 

1518 :param page_size: 

1519 (Optional) Maximum number of blobs to return in each page. 

1520 Defaults to a value set by the API. 

1521 

1522 :rtype: :class:`~google.api_core.page_iterator.Iterator` 

1523 :returns: Iterator of all :class:`~google.cloud.storage.blob.Blob` 

1524 in this bucket matching the arguments. 

1525 """ 

1526 with create_trace_span(name="Storage.Bucket.listBlobs"): 

1527 client = self._require_client(client) 

1528 return client.list_blobs( 

1529 self, 

1530 max_results=max_results, 

1531 page_token=page_token, 

1532 prefix=prefix, 

1533 delimiter=delimiter, 

1534 start_offset=start_offset, 

1535 end_offset=end_offset, 

1536 include_trailing_delimiter=include_trailing_delimiter, 

1537 versions=versions, 

1538 projection=projection, 

1539 fields=fields, 

1540 page_size=page_size, 

1541 timeout=timeout, 

1542 retry=retry, 

1543 match_glob=match_glob, 

1544 include_folders_as_prefixes=include_folders_as_prefixes, 

1545 soft_deleted=soft_deleted, 

1546 ) 

1547 

1548 def list_notifications( 

1549 self, client=None, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY 

1550 ): 

1551 """List Pub / Sub notifications for this bucket. 

1552 

1553 See: 

1554 https://cloud.google.com/storage/docs/json_api/v1/notifications/list 

1555 

1556 If :attr:`user_project` is set, bills the API request to that project. 

1557 

1558 :type client: :class:`~google.cloud.storage.client.Client` or 

1559 ``NoneType`` 

1560 :param client: (Optional) The client to use. If not passed, falls back 

1561 to the ``client`` stored on the current bucket. 

1562 :type timeout: float or tuple 

1563 :param timeout: 

1564 (Optional) The amount of time, in seconds, to wait 

1565 for the server response. See: :ref:`configuring_timeouts` 

1566 

1567 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1568 :param retry: 

1569 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

1570 

1571 :rtype: list of :class:`.BucketNotification` 

1572 :returns: notification instances 

1573 """ 

1574 with create_trace_span(name="Storage.Bucket.listNotifications"): 

1575 client = self._require_client(client) 

1576 path = self.path + "/notificationConfigs" 

1577 iterator = client._list_resource( 

1578 path, 

1579 _item_to_notification, 

1580 timeout=timeout, 

1581 retry=retry, 

1582 ) 

1583 iterator.bucket = self 

1584 return iterator 

1585 

1586 def get_notification( 

1587 self, 

1588 notification_id, 

1589 client=None, 

1590 timeout=_DEFAULT_TIMEOUT, 

1591 retry=DEFAULT_RETRY, 

1592 ): 

1593 """Get Pub / Sub notification for this bucket. 

1594 

1595 See [API reference docs](https://cloud.google.com/storage/docs/json_api/v1/notifications/get) 

1596 and a [code sample](https://cloud.google.com/storage/docs/samples/storage-print-pubsub-bucket-notification#storage_print_pubsub_bucket_notification-python). 

1597 

1598 If :attr:`user_project` is set, bills the API request to that project. 

1599 

1600 :type notification_id: str 

1601 :param notification_id: The notification id to retrieve the notification configuration. 

1602 

1603 :type client: :class:`~google.cloud.storage.client.Client` or 

1604 ``NoneType`` 

1605 :param client: (Optional) The client to use. If not passed, falls back 

1606 to the ``client`` stored on the current bucket. 

1607 :type timeout: float or tuple 

1608 :param timeout: 

1609 (Optional) The amount of time, in seconds, to wait 

1610 for the server response. See: :ref:`configuring_timeouts` 

1611 

1612 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1613 :param retry: 

1614 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

1615 

1616 :rtype: :class:`.BucketNotification` 

1617 :returns: notification instance. 

1618 """ 

1619 with create_trace_span(name="Storage.Bucket.getNotification"): 

1620 notification = self.notification(notification_id=notification_id) 

1621 notification.reload(client=client, timeout=timeout, retry=retry) 

1622 return notification 

1623 

1624 def delete( 

1625 self, 

1626 force=False, 

1627 client=None, 

1628 if_metageneration_match=None, 

1629 if_metageneration_not_match=None, 

1630 timeout=_DEFAULT_TIMEOUT, 

1631 retry=DEFAULT_RETRY, 

1632 ): 

1633 """Delete this bucket. 

1634 

1635 The bucket **must** be empty in order to submit a delete request. If 

1636 ``force=True`` is passed, this will first attempt to delete all the 

1637 objects / blobs in the bucket (i.e. try to empty the bucket). 

1638 

1639 If the bucket doesn't exist, this will raise 

1640 :class:`google.cloud.exceptions.NotFound`. If the bucket is not empty 

1641 (and ``force=False``), will raise :class:`google.cloud.exceptions.Conflict`. 

1642 

1643 If ``force=True`` and the bucket contains more than 256 objects / blobs 

1644 this will cowardly refuse to delete the objects (or the bucket). This 

1645 is to prevent accidental bucket deletion and to prevent extremely long 

1646 runtime of this method. Also note that ``force=True`` is not supported 

1647 in a ``Batch`` context. 

1648 

1649 If :attr:`user_project` is set, bills the API request to that project. 

1650 

1651 :type force: bool 

1652 :param force: If True, empties the bucket's objects then deletes it. 

1653 

1654 :type client: :class:`~google.cloud.storage.client.Client` or 

1655 ``NoneType`` 

1656 :param client: (Optional) The client to use. If not passed, falls back 

1657 to the ``client`` stored on the current bucket. 

1658 

1659 :type if_metageneration_match: long 

1660 :param if_metageneration_match: (Optional) Make the operation conditional on whether the 

1661 blob's current metageneration matches the given value. 

1662 

1663 :type if_metageneration_not_match: long 

1664 :param if_metageneration_not_match: (Optional) Make the operation conditional on whether the 

1665 blob's current metageneration does not match the given value. 

1666 

1667 :type timeout: float or tuple 

1668 :param timeout: 

1669 (Optional) The amount of time, in seconds, to wait 

1670 for the server response. See: :ref:`configuring_timeouts` 

1671 

1672 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1673 :param retry: 

1674 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

1675 

1676 :raises: :class:`ValueError` if ``force`` is ``True`` and the bucket 

1677 contains more than 256 objects / blobs. 

1678 """ 

1679 with create_trace_span(name="Storage.Bucket.delete"): 

1680 client = self._require_client(client) 

1681 query_params = {} 

1682 

1683 if self.user_project is not None: 

1684 query_params["userProject"] = self.user_project 

1685 

1686 _add_generation_match_parameters( 

1687 query_params, 

1688 if_metageneration_match=if_metageneration_match, 

1689 if_metageneration_not_match=if_metageneration_not_match, 

1690 ) 

1691 if force: 

1692 blobs = list( 

1693 self.list_blobs( 

1694 max_results=self._MAX_OBJECTS_FOR_ITERATION + 1, 

1695 client=client, 

1696 timeout=timeout, 

1697 retry=retry, 

1698 versions=True, 

1699 ) 

1700 ) 

1701 if len(blobs) > self._MAX_OBJECTS_FOR_ITERATION: 

1702 message = ( 

1703 "Refusing to delete bucket with more than " 

1704 "%d objects. If you actually want to delete " 

1705 "this bucket, please delete the objects " 

1706 "yourself before calling Bucket.delete()." 

1707 ) % (self._MAX_OBJECTS_FOR_ITERATION,) 

1708 raise ValueError(message) 

1709 

1710 # Ignore 404 errors on delete. 

1711 self.delete_blobs( 

1712 blobs, 

1713 on_error=lambda blob: None, 

1714 client=client, 

1715 timeout=timeout, 

1716 retry=retry, 

1717 preserve_generation=True, 

1718 ) 

1719 

1720 # We intentionally pass `_target_object=None` since a DELETE 

1721 # request has no response value (whether in a standard request or 

1722 # in a batch request). 

1723 client._delete_resource( 

1724 self.path, 

1725 query_params=query_params, 

1726 timeout=timeout, 

1727 retry=retry, 

1728 _target_object=None, 

1729 ) 

1730 

1731 def delete_blob( 

1732 self, 

1733 blob_name, 

1734 client=None, 

1735 generation=None, 

1736 if_generation_match=None, 

1737 if_generation_not_match=None, 

1738 if_metageneration_match=None, 

1739 if_metageneration_not_match=None, 

1740 timeout=_DEFAULT_TIMEOUT, 

1741 retry=DEFAULT_RETRY, 

1742 ): 

1743 """Deletes a blob from the current bucket. 

1744 

1745 If :attr:`user_project` is set, bills the API request to that project. 

1746 

1747 :type blob_name: str 

1748 :param blob_name: A blob name to delete. 

1749 

1750 :type client: :class:`~google.cloud.storage.client.Client` or 

1751 ``NoneType`` 

1752 :param client: (Optional) The client to use. If not passed, falls back 

1753 to the ``client`` stored on the current bucket. 

1754 

1755 :type generation: long 

1756 :param generation: (Optional) If present, permanently deletes a specific 

1757 revision of this object. 

1758 

1759 :type if_generation_match: long 

1760 :param if_generation_match: 

1761 (Optional) See :ref:`using-if-generation-match` 

1762 

1763 :type if_generation_not_match: long 

1764 :param if_generation_not_match: 

1765 (Optional) See :ref:`using-if-generation-not-match` 

1766 

1767 :type if_metageneration_match: long 

1768 :param if_metageneration_match: 

1769 (Optional) See :ref:`using-if-metageneration-match` 

1770 

1771 :type if_metageneration_not_match: long 

1772 :param if_metageneration_not_match: 

1773 (Optional) See :ref:`using-if-metageneration-not-match` 

1774 

1775 :type timeout: float or tuple 

1776 :param timeout: 

1777 (Optional) The amount of time, in seconds, to wait 

1778 for the server response. See: :ref:`configuring_timeouts` 

1779 

1780 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1781 :param retry: (Optional) How to retry the RPC. A None value will disable 

1782 retries. A google.api_core.retry.Retry value will enable retries, 

1783 and the object will define retriable response codes and errors and 

1784 configure backoff and timeout options. 

1785 

1786 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a 

1787 Retry object and activates it only if certain conditions are met. 

1788 This class exists to provide safe defaults for RPC calls that are 

1789 not technically safe to retry normally (due to potential data 

1790 duplication or other side-effects) but become safe to retry if a 

1791 condition such as if_generation_match is set. 

1792 

1793 See the retry.py source code and docstrings in this package 

1794 (google.cloud.storage.retry) for information on retry types and how 

1795 to configure them. 

1796 

1797 :raises: :class:`google.cloud.exceptions.NotFound` Raises a NotFound 

1798 if the blob isn't found. To suppress 

1799 the exception, use :meth:`delete_blobs` by passing a no-op 

1800 ``on_error`` callback. 

1801 """ 

1802 with create_trace_span(name="Storage.Bucket.deleteBlob"): 

1803 client = self._require_client(client) 

1804 blob = Blob(blob_name, bucket=self, generation=generation) 

1805 

1806 query_params = copy.deepcopy(blob._query_params) 

1807 _add_generation_match_parameters( 

1808 query_params, 

1809 if_generation_match=if_generation_match, 

1810 if_generation_not_match=if_generation_not_match, 

1811 if_metageneration_match=if_metageneration_match, 

1812 if_metageneration_not_match=if_metageneration_not_match, 

1813 ) 

1814 # We intentionally pass `_target_object=None` since a DELETE 

1815 # request has no response value (whether in a standard request or 

1816 # in a batch request). 

1817 client._delete_resource( 

1818 blob.path, 

1819 query_params=query_params, 

1820 timeout=timeout, 

1821 retry=retry, 

1822 _target_object=None, 

1823 ) 

1824 

1825 def delete_blobs( 

1826 self, 

1827 blobs, 

1828 on_error=None, 

1829 client=None, 

1830 preserve_generation=False, 

1831 timeout=_DEFAULT_TIMEOUT, 

1832 if_generation_match=None, 

1833 if_generation_not_match=None, 

1834 if_metageneration_match=None, 

1835 if_metageneration_not_match=None, 

1836 retry=DEFAULT_RETRY, 

1837 ): 

1838 """Deletes a list of blobs from the current bucket. 

1839 

1840 Uses :meth:`delete_blob` to delete each individual blob. 

1841 

1842 By default, any generation information in the list of blobs is ignored, and the 

1843 live versions of all blobs are deleted. Set `preserve_generation` to True 

1844 if blob generation should instead be propagated from the list of blobs. 

1845 

1846 If :attr:`user_project` is set, bills the API request to that project. 

1847 

1848 :type blobs: list 

1849 :param blobs: A list of :class:`~google.cloud.storage.blob.Blob`-s or 

1850 blob names to delete. 

1851 

1852 :type on_error: callable 

1853 :param on_error: (Optional) Takes single argument: ``blob``. 

1854 Called once for each blob raising 

1855 :class:`~google.cloud.exceptions.NotFound`; 

1856 otherwise, the exception is propagated. 

1857 Note that ``on_error`` is not supported in a ``Batch`` context. 

1858 

1859 :type client: :class:`~google.cloud.storage.client.Client` 

1860 :param client: (Optional) The client to use. If not passed, falls back 

1861 to the ``client`` stored on the current bucket. 

1862 

1863 :type preserve_generation: bool 

1864 :param preserve_generation: (Optional) Deletes only the generation specified on the blob object, 

1865 instead of the live version, if set to True. Only :class:~google.cloud.storage.blob.Blob 

1866 objects can have their generation set in this way. 

1867 Default: False. 

1868 

1869 :type if_generation_match: list of long 

1870 :param if_generation_match: 

1871 (Optional) See :ref:`using-if-generation-match` 

1872 Note that the length of the list must match the length of 

1873 The list must match ``blobs`` item-to-item. 

1874 

1875 :type if_generation_not_match: list of long 

1876 :param if_generation_not_match: 

1877 (Optional) See :ref:`using-if-generation-not-match` 

1878 The list must match ``blobs`` item-to-item. 

1879 

1880 :type if_metageneration_match: list of long 

1881 :param if_metageneration_match: 

1882 (Optional) See :ref:`using-if-metageneration-match` 

1883 The list must match ``blobs`` item-to-item. 

1884 

1885 :type if_metageneration_not_match: list of long 

1886 :param if_metageneration_not_match: 

1887 (Optional) See :ref:`using-if-metageneration-not-match` 

1888 The list must match ``blobs`` item-to-item. 

1889 

1890 :type timeout: float or tuple 

1891 :param timeout: 

1892 (Optional) The amount of time, in seconds, to wait 

1893 for the server response. See: :ref:`configuring_timeouts` 

1894 

1895 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

1896 :param retry: (Optional) How to retry the RPC. A None value will disable 

1897 retries. A google.api_core.retry.Retry value will enable retries, 

1898 and the object will define retriable response codes and errors and 

1899 configure backoff and timeout options. 

1900 

1901 A google.cloud.storage.retry.ConditionalRetryPolicy value wraps a 

1902 Retry object and activates it only if certain conditions are met. 

1903 This class exists to provide safe defaults for RPC calls that are 

1904 not technically safe to retry normally (due to potential data 

1905 duplication or other side-effects) but become safe to retry if a 

1906 condition such as if_generation_match is set. 

1907 

1908 See the retry.py source code and docstrings in this package 

1909 (google.cloud.storage.retry) for information on retry types and how 

1910 to configure them. 

1911 

1912 :raises: :class:`~google.cloud.exceptions.NotFound` (if 

1913 `on_error` is not passed). 

1914 """ 

1915 with create_trace_span(name="Storage.Bucket.deleteBlobs"): 

1916 _raise_if_len_differs( 

1917 len(blobs), 

1918 if_generation_match=if_generation_match, 

1919 if_generation_not_match=if_generation_not_match, 

1920 if_metageneration_match=if_metageneration_match, 

1921 if_metageneration_not_match=if_metageneration_not_match, 

1922 ) 

1923 if_generation_match = iter(if_generation_match or []) 

1924 if_generation_not_match = iter(if_generation_not_match or []) 

1925 if_metageneration_match = iter(if_metageneration_match or []) 

1926 if_metageneration_not_match = iter(if_metageneration_not_match or []) 

1927 

1928 for blob in blobs: 

1929 try: 

1930 blob_name = blob 

1931 generation = None 

1932 if not isinstance(blob_name, str): 

1933 blob_name = blob.name 

1934 generation = blob.generation if preserve_generation else None 

1935 

1936 self.delete_blob( 

1937 blob_name, 

1938 client=client, 

1939 generation=generation, 

1940 if_generation_match=next(if_generation_match, None), 

1941 if_generation_not_match=next(if_generation_not_match, None), 

1942 if_metageneration_match=next(if_metageneration_match, None), 

1943 if_metageneration_not_match=next( 

1944 if_metageneration_not_match, None 

1945 ), 

1946 timeout=timeout, 

1947 retry=retry, 

1948 ) 

1949 except NotFound: 

1950 if on_error is not None: 

1951 on_error(blob) 

1952 else: 

1953 raise 

1954 

1955 def copy_blob( 

1956 self, 

1957 blob, 

1958 destination_bucket, 

1959 new_name=None, 

1960 client=None, 

1961 preserve_acl=True, 

1962 source_generation=None, 

1963 if_generation_match=None, 

1964 if_generation_not_match=None, 

1965 if_metageneration_match=None, 

1966 if_metageneration_not_match=None, 

1967 if_source_generation_match=None, 

1968 if_source_generation_not_match=None, 

1969 if_source_metageneration_match=None, 

1970 if_source_metageneration_not_match=None, 

1971 timeout=_DEFAULT_TIMEOUT, 

1972 retry=DEFAULT_RETRY_IF_GENERATION_SPECIFIED, 

1973 ): 

1974 """Copy the given blob to the given bucket, optionally with a new name. 

1975 

1976 If :attr:`user_project` is set, bills the API request to that project. 

1977 

1978 See [API reference docs](https://cloud.google.com/storage/docs/json_api/v1/objects/copy) 

1979 and a [code sample](https://cloud.google.com/storage/docs/samples/storage-copy-file#storage_copy_file-python). 

1980 

1981 :type blob: :class:`google.cloud.storage.blob.Blob` 

1982 :param blob: The blob to be copied. 

1983 

1984 :type destination_bucket: :class:`google.cloud.storage.bucket.Bucket` 

1985 :param destination_bucket: The bucket into which the blob should be 

1986 copied. 

1987 

1988 :type new_name: str 

1989 :param new_name: (Optional) The new name for the copied file. 

1990 

1991 :type client: :class:`~google.cloud.storage.client.Client` or 

1992 ``NoneType`` 

1993 :param client: (Optional) The client to use. If not passed, falls back 

1994 to the ``client`` stored on the current bucket. 

1995 

1996 :type preserve_acl: bool 

1997 :param preserve_acl: DEPRECATED. This argument is not functional! 

1998 (Optional) Copies ACL from old blob to new blob. 

1999 Default: True. 

2000 Note that ``preserve_acl`` is not supported in a 

2001 ``Batch`` context. 

2002 

2003 :type source_generation: long 

2004 :param source_generation: (Optional) The generation of the blob to be 

2005 copied. 

2006 

2007 :type if_generation_match: long 

2008 :param if_generation_match: 

2009 (Optional) See :ref:`using-if-generation-match` 

2010 Note that the generation to be matched is that of the 

2011 ``destination`` blob. 

2012 

2013 :type if_generation_not_match: long 

2014 :param if_generation_not_match: 

2015 (Optional) See :ref:`using-if-generation-not-match` 

2016 Note that the generation to be matched is that of the 

2017 ``destination`` blob. 

2018 

2019 :type if_metageneration_match: long 

2020 :param if_metageneration_match: 

2021 (Optional) See :ref:`using-if-metageneration-match` 

2022 Note that the metageneration to be matched is that of the 

2023 ``destination`` blob. 

2024 

2025 :type if_metageneration_not_match: long 

2026 :param if_metageneration_not_match: 

2027 (Optional) See :ref:`using-if-metageneration-not-match` 

2028 Note that the metageneration to be matched is that of the 

2029 ``destination`` blob. 

2030 

2031 :type if_source_generation_match: long 

2032 :param if_source_generation_match: 

2033 (Optional) Makes the operation conditional on whether the source 

2034 object's generation matches the given value. 

2035 

2036 :type if_source_generation_not_match: long 

2037 :param if_source_generation_not_match: 

2038 (Optional) Makes the operation conditional on whether the source 

2039 object's generation does not match the given value. 

2040 

2041 :type if_source_metageneration_match: long 

2042 :param if_source_metageneration_match: 

2043 (Optional) Makes the operation conditional on whether the source 

2044 object's current metageneration matches the given value. 

2045 

2046 :type if_source_metageneration_not_match: long 

2047 :param if_source_metageneration_not_match: 

2048 (Optional) Makes the operation conditional on whether the source 

2049 object's current metageneration does not match the given value. 

2050 

2051 :type timeout: float or tuple 

2052 :param timeout: 

2053 (Optional) The amount of time, in seconds, to wait 

2054 for the server response. See: :ref:`configuring_timeouts` 

2055 

2056 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

2057 :param retry: 

2058 (Optional) How to retry the RPC. 

2059 The default value is ``DEFAULT_RETRY_IF_GENERATION_SPECIFIED``, a conditional retry 

2060 policy which will only enable retries if ``if_generation_match`` or ``generation`` 

2061 is set, in order to ensure requests are idempotent before retrying them. 

2062 Change the value to ``DEFAULT_RETRY`` or another `google.api_core.retry.Retry` object 

2063 to enable retries regardless of generation precondition setting. 

2064 See [Configuring Retries](https://cloud.google.com/python/docs/reference/storage/latest/retry_timeout). 

2065 

2066 :rtype: :class:`google.cloud.storage.blob.Blob` 

2067 :returns: The new Blob. 

2068 """ 

2069 with create_trace_span(name="Storage.Bucket.copyBlob"): 

2070 client = self._require_client(client) 

2071 query_params = {} 

2072 

2073 if self.user_project is not None: 

2074 query_params["userProject"] = self.user_project 

2075 

2076 if source_generation is not None: 

2077 query_params["sourceGeneration"] = source_generation 

2078 

2079 _add_generation_match_parameters( 

2080 query_params, 

2081 if_generation_match=if_generation_match, 

2082 if_generation_not_match=if_generation_not_match, 

2083 if_metageneration_match=if_metageneration_match, 

2084 if_metageneration_not_match=if_metageneration_not_match, 

2085 if_source_generation_match=if_source_generation_match, 

2086 if_source_generation_not_match=if_source_generation_not_match, 

2087 if_source_metageneration_match=if_source_metageneration_match, 

2088 if_source_metageneration_not_match=if_source_metageneration_not_match, 

2089 ) 

2090 

2091 if new_name is None: 

2092 new_name = blob.name 

2093 

2094 new_blob = Blob(bucket=destination_bucket, name=new_name) 

2095 api_path = blob.path + "/copyTo" + new_blob.path 

2096 copy_result = client._post_resource( 

2097 api_path, 

2098 None, 

2099 query_params=query_params, 

2100 timeout=timeout, 

2101 retry=retry, 

2102 _target_object=new_blob, 

2103 ) 

2104 

2105 if not preserve_acl: 

2106 new_blob.acl.save(acl={}, client=client, timeout=timeout) 

2107 

2108 new_blob._set_properties(copy_result) 

2109 return new_blob 

2110 

2111 def rename_blob( 

2112 self, 

2113 blob, 

2114 new_name, 

2115 client=None, 

2116 if_generation_match=None, 

2117 if_generation_not_match=None, 

2118 if_metageneration_match=None, 

2119 if_metageneration_not_match=None, 

2120 if_source_generation_match=None, 

2121 if_source_generation_not_match=None, 

2122 if_source_metageneration_match=None, 

2123 if_source_metageneration_not_match=None, 

2124 timeout=_DEFAULT_TIMEOUT, 

2125 retry=DEFAULT_RETRY_IF_GENERATION_SPECIFIED, 

2126 ): 

2127 """Rename the given blob using copy and delete operations. 

2128 

2129 If :attr:`user_project` is set, bills the API request to that project. 

2130 

2131 Effectively, copies blob to the same bucket with a new name, then 

2132 deletes the blob. 

2133 

2134 .. warning:: 

2135 

2136 This method will first duplicate the data and then delete the 

2137 old blob. This means that with very large objects renaming 

2138 could be a very (temporarily) costly or a very slow operation. 

2139 If you need more control over the copy and deletion, instead 

2140 use ``google.cloud.storage.blob.Blob.copy_to`` and 

2141 ``google.cloud.storage.blob.Blob.delete`` directly. 

2142 

2143 Also note that this method is not fully supported in a 

2144 ``Batch`` context. 

2145 

2146 :type blob: :class:`google.cloud.storage.blob.Blob` 

2147 :param blob: The blob to be renamed. 

2148 

2149 :type new_name: str 

2150 :param new_name: The new name for this blob. 

2151 

2152 :type client: :class:`~google.cloud.storage.client.Client` or 

2153 ``NoneType`` 

2154 :param client: (Optional) The client to use. If not passed, falls back 

2155 to the ``client`` stored on the current bucket. 

2156 

2157 :type if_generation_match: long 

2158 :param if_generation_match: 

2159 (Optional) See :ref:`using-if-generation-match` 

2160 Note that the generation to be matched is that of the 

2161 ``destination`` blob. 

2162 

2163 :type if_generation_not_match: long 

2164 :param if_generation_not_match: 

2165 (Optional) See :ref:`using-if-generation-not-match` 

2166 Note that the generation to be matched is that of the 

2167 ``destination`` blob. 

2168 

2169 :type if_metageneration_match: long 

2170 :param if_metageneration_match: 

2171 (Optional) See :ref:`using-if-metageneration-match` 

2172 Note that the metageneration to be matched is that of the 

2173 ``destination`` blob. 

2174 

2175 :type if_metageneration_not_match: long 

2176 :param if_metageneration_not_match: 

2177 (Optional) See :ref:`using-if-metageneration-not-match` 

2178 Note that the metageneration to be matched is that of the 

2179 ``destination`` blob. 

2180 

2181 :type if_source_generation_match: long 

2182 :param if_source_generation_match: 

2183 (Optional) Makes the operation conditional on whether the source 

2184 object's generation matches the given value. Also used in the 

2185 (implied) delete request. 

2186 

2187 :type if_source_generation_not_match: long 

2188 :param if_source_generation_not_match: 

2189 (Optional) Makes the operation conditional on whether the source 

2190 object's generation does not match the given value. Also used in 

2191 the (implied) delete request. 

2192 

2193 :type if_source_metageneration_match: long 

2194 :param if_source_metageneration_match: 

2195 (Optional) Makes the operation conditional on whether the source 

2196 object's current metageneration matches the given value. Also used 

2197 in the (implied) delete request. 

2198 

2199 :type if_source_metageneration_not_match: long 

2200 :param if_source_metageneration_not_match: 

2201 (Optional) Makes the operation conditional on whether the source 

2202 object's current metageneration does not match the given value. 

2203 Also used in the (implied) delete request. 

2204 

2205 :type timeout: float or tuple 

2206 :param timeout: 

2207 (Optional) The amount of time, in seconds, to wait 

2208 for the server response. See: :ref:`configuring_timeouts` 

2209 

2210 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

2211 :param retry: 

2212 (Optional) How to retry the RPC. 

2213 The default value is ``DEFAULT_RETRY_IF_GENERATION_SPECIFIED``, a conditional retry 

2214 policy which will only enable retries if ``if_generation_match`` or ``generation`` 

2215 is set, in order to ensure requests are idempotent before retrying them. 

2216 Change the value to ``DEFAULT_RETRY`` or another `google.api_core.retry.Retry` object 

2217 to enable retries regardless of generation precondition setting. 

2218 See [Configuring Retries](https://cloud.google.com/python/docs/reference/storage/latest/retry_timeout). 

2219 

2220 :rtype: :class:`Blob` 

2221 :returns: The newly-renamed blob. 

2222 """ 

2223 with create_trace_span(name="Storage.Bucket.renameBlob"): 

2224 same_name = blob.name == new_name 

2225 

2226 new_blob = self.copy_blob( 

2227 blob, 

2228 self, 

2229 new_name, 

2230 client=client, 

2231 timeout=timeout, 

2232 if_generation_match=if_generation_match, 

2233 if_generation_not_match=if_generation_not_match, 

2234 if_metageneration_match=if_metageneration_match, 

2235 if_metageneration_not_match=if_metageneration_not_match, 

2236 if_source_generation_match=if_source_generation_match, 

2237 if_source_generation_not_match=if_source_generation_not_match, 

2238 if_source_metageneration_match=if_source_metageneration_match, 

2239 if_source_metageneration_not_match=if_source_metageneration_not_match, 

2240 retry=retry, 

2241 ) 

2242 

2243 if not same_name: 

2244 blob.delete( 

2245 client=client, 

2246 timeout=timeout, 

2247 if_generation_match=if_source_generation_match, 

2248 if_generation_not_match=if_source_generation_not_match, 

2249 if_metageneration_match=if_source_metageneration_match, 

2250 if_metageneration_not_match=if_source_metageneration_not_match, 

2251 retry=retry, 

2252 ) 

2253 return new_blob 

2254 

2255 def move_blob( 

2256 self, 

2257 blob, 

2258 new_name, 

2259 client=None, 

2260 if_generation_match=None, 

2261 if_generation_not_match=None, 

2262 if_metageneration_match=None, 

2263 if_metageneration_not_match=None, 

2264 if_source_generation_match=None, 

2265 if_source_generation_not_match=None, 

2266 if_source_metageneration_match=None, 

2267 if_source_metageneration_not_match=None, 

2268 timeout=_DEFAULT_TIMEOUT, 

2269 retry=DEFAULT_RETRY_IF_GENERATION_SPECIFIED, 

2270 ): 

2271 """Move a blob to a new name atomically. 

2272 

2273 If :attr:`user_project` is set on the bucket, bills the API request to that project. 

2274 

2275 :type blob: :class:`google.cloud.storage.blob.Blob` 

2276 :param blob: The blob to be renamed. 

2277 

2278 :type new_name: str 

2279 :param new_name: The new name for this blob. 

2280 

2281 :type client: :class:`~google.cloud.storage.client.Client` or 

2282 ``NoneType`` 

2283 :param client: (Optional) The client to use. If not passed, falls back 

2284 to the ``client`` stored on the current bucket. 

2285 

2286 :type if_generation_match: int 

2287 :param if_generation_match: 

2288 (Optional) See :ref:`using-if-generation-match` 

2289 Note that the generation to be matched is that of the 

2290 ``destination`` blob. 

2291 

2292 :type if_generation_not_match: int 

2293 :param if_generation_not_match: 

2294 (Optional) See :ref:`using-if-generation-not-match` 

2295 Note that the generation to be matched is that of the 

2296 ``destination`` blob. 

2297 

2298 :type if_metageneration_match: int 

2299 :param if_metageneration_match: 

2300 (Optional) See :ref:`using-if-metageneration-match` 

2301 Note that the metageneration to be matched is that of the 

2302 ``destination`` blob. 

2303 

2304 :type if_metageneration_not_match: int 

2305 :param if_metageneration_not_match: 

2306 (Optional) See :ref:`using-if-metageneration-not-match` 

2307 Note that the metageneration to be matched is that of the 

2308 ``destination`` blob. 

2309 

2310 :type if_source_generation_match: int 

2311 :param if_source_generation_match: 

2312 (Optional) Makes the operation conditional on whether the source 

2313 object's generation matches the given value. 

2314 

2315 :type if_source_generation_not_match: int 

2316 :param if_source_generation_not_match: 

2317 (Optional) Makes the operation conditional on whether the source 

2318 object's generation does not match the given value. 

2319 

2320 :type if_source_metageneration_match: int 

2321 :param if_source_metageneration_match: 

2322 (Optional) Makes the operation conditional on whether the source 

2323 object's current metageneration matches the given value. 

2324 

2325 :type if_source_metageneration_not_match: int 

2326 :param if_source_metageneration_not_match: 

2327 (Optional) Makes the operation conditional on whether the source 

2328 object's current metageneration does not match the given value. 

2329 

2330 :type timeout: float or tuple 

2331 :param timeout: 

2332 (Optional) The amount of time, in seconds, to wait 

2333 for the server response. See: :ref:`configuring_timeouts` 

2334 

2335 :type retry: google.api_core.retry.Retry 

2336 :param retry: 

2337 (Optional) How to retry the RPC. 

2338 See [Configuring Retries](https://cloud.google.com/python/docs/reference/storage/latest/retry_timeout). 

2339 

2340 :rtype: :class:`Blob` 

2341 :returns: The newly-moved blob. 

2342 """ 

2343 with create_trace_span(name="Storage.Bucket.moveBlob"): 

2344 client = self._require_client(client) 

2345 query_params = {} 

2346 

2347 if self.user_project is not None: 

2348 query_params["userProject"] = self.user_project 

2349 

2350 _add_generation_match_parameters( 

2351 query_params, 

2352 if_generation_match=if_generation_match, 

2353 if_generation_not_match=if_generation_not_match, 

2354 if_metageneration_match=if_metageneration_match, 

2355 if_metageneration_not_match=if_metageneration_not_match, 

2356 if_source_generation_match=if_source_generation_match, 

2357 if_source_generation_not_match=if_source_generation_not_match, 

2358 if_source_metageneration_match=if_source_metageneration_match, 

2359 if_source_metageneration_not_match=if_source_metageneration_not_match, 

2360 ) 

2361 

2362 new_blob = Blob(bucket=self, name=new_name) 

2363 api_path = blob.path + "/moveTo/o/" + new_blob.name 

2364 move_result = client._post_resource( 

2365 api_path, 

2366 None, 

2367 query_params=query_params, 

2368 timeout=timeout, 

2369 retry=retry, 

2370 _target_object=new_blob, 

2371 ) 

2372 

2373 new_blob._set_properties(move_result) 

2374 return new_blob 

2375 

2376 def restore_blob( 

2377 self, 

2378 blob_name, 

2379 client=None, 

2380 generation=None, 

2381 copy_source_acl=None, 

2382 projection=None, 

2383 if_generation_match=None, 

2384 if_generation_not_match=None, 

2385 if_metageneration_match=None, 

2386 if_metageneration_not_match=None, 

2387 timeout=_DEFAULT_TIMEOUT, 

2388 retry=DEFAULT_RETRY_IF_GENERATION_SPECIFIED, 

2389 ): 

2390 """Restores a soft-deleted object. 

2391 

2392 If :attr:`user_project` is set on the bucket, bills the API request to that project. 

2393 

2394 See [API reference docs](https://cloud.google.com/storage/docs/json_api/v1/objects/restore) 

2395 

2396 :type blob_name: str 

2397 :param blob_name: The name of the blob to be restored. 

2398 

2399 :type client: :class:`~google.cloud.storage.client.Client` 

2400 :param client: (Optional) The client to use. If not passed, falls back 

2401 to the ``client`` stored on the current bucket. 

2402 

2403 :type generation: int 

2404 :param generation: Selects the specific revision of the object. 

2405 

2406 :type copy_source_acl: bool 

2407 :param copy_source_acl: (Optional) If true, copy the soft-deleted object's access controls. 

2408 

2409 :type projection: str 

2410 :param projection: (Optional) Specifies the set of properties to return. 

2411 If used, must be 'full' or 'noAcl'. 

2412 

2413 :type if_generation_match: long 

2414 :param if_generation_match: 

2415 (Optional) See :ref:`using-if-generation-match` 

2416 

2417 :type if_generation_not_match: long 

2418 :param if_generation_not_match: 

2419 (Optional) See :ref:`using-if-generation-not-match` 

2420 

2421 :type if_metageneration_match: long 

2422 :param if_metageneration_match: 

2423 (Optional) See :ref:`using-if-metageneration-match` 

2424 

2425 :type if_metageneration_not_match: long 

2426 :param if_metageneration_not_match: 

2427 (Optional) See :ref:`using-if-metageneration-not-match` 

2428 

2429 :type timeout: float or tuple 

2430 :param timeout: 

2431 (Optional) The amount of time, in seconds, to wait 

2432 for the server response. See: :ref:`configuring_timeouts` 

2433 

2434 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

2435 :param retry: 

2436 (Optional) How to retry the RPC. 

2437 The default value is ``DEFAULT_RETRY_IF_GENERATION_SPECIFIED``, which 

2438 only restore operations with ``if_generation_match`` or ``generation`` set 

2439 will be retried. 

2440 

2441 Users can configure non-default retry behavior. A ``None`` value will 

2442 disable retries. A ``DEFAULT_RETRY`` value will enable retries 

2443 even if restore operations are not guaranteed to be idempotent. 

2444 See [Configuring Retries](https://cloud.google.com/python/docs/reference/storage/latest/retry_timeout). 

2445 

2446 :rtype: :class:`google.cloud.storage.blob.Blob` 

2447 :returns: The restored Blob. 

2448 """ 

2449 with create_trace_span(name="Storage.Bucket.restore_blob"): 

2450 client = self._require_client(client) 

2451 query_params = {} 

2452 

2453 if self.user_project is not None: 

2454 query_params["userProject"] = self.user_project 

2455 if generation is not None: 

2456 query_params["generation"] = generation 

2457 if copy_source_acl is not None: 

2458 query_params["copySourceAcl"] = copy_source_acl 

2459 if projection is not None: 

2460 query_params["projection"] = projection 

2461 

2462 _add_generation_match_parameters( 

2463 query_params, 

2464 if_generation_match=if_generation_match, 

2465 if_generation_not_match=if_generation_not_match, 

2466 if_metageneration_match=if_metageneration_match, 

2467 if_metageneration_not_match=if_metageneration_not_match, 

2468 ) 

2469 

2470 blob = Blob(bucket=self, name=blob_name) 

2471 api_response = client._post_resource( 

2472 f"{blob.path}/restore", 

2473 None, 

2474 query_params=query_params, 

2475 timeout=timeout, 

2476 retry=retry, 

2477 ) 

2478 blob._set_properties(api_response) 

2479 return blob 

2480 

2481 @property 

2482 def cors(self): 

2483 """Retrieve or set CORS policies configured for this bucket. 

2484 

2485 See http://www.w3.org/TR/cors/ and 

2486 https://cloud.google.com/storage/docs/json_api/v1/buckets 

2487 

2488 .. note:: 

2489 

2490 The getter for this property returns a list which contains 

2491 *copies* of the bucket's CORS policy mappings. Mutating the list 

2492 or one of its dicts has no effect unless you then re-assign the 

2493 dict via the setter. E.g.: 

2494 

2495 >>> policies = bucket.cors 

2496 >>> policies.append({'origin': '/foo', ...}) 

2497 >>> policies[1]['maxAgeSeconds'] = 3600 

2498 >>> del policies[0] 

2499 >>> bucket.cors = policies 

2500 >>> bucket.update() 

2501 

2502 :setter: Set CORS policies for this bucket. 

2503 :getter: Gets the CORS policies for this bucket. 

2504 

2505 :rtype: list of dictionaries 

2506 :returns: A sequence of mappings describing each CORS policy. 

2507 """ 

2508 return [copy.deepcopy(policy) for policy in self._properties.get("cors", ())] 

2509 

2510 @cors.setter 

2511 def cors(self, entries): 

2512 """Set CORS policies configured for this bucket. 

2513 

2514 See http://www.w3.org/TR/cors/ and 

2515 https://cloud.google.com/storage/docs/json_api/v1/buckets 

2516 

2517 :type entries: list of dictionaries 

2518 :param entries: A sequence of mappings describing each CORS policy. 

2519 """ 

2520 self._patch_property("cors", entries) 

2521 

2522 default_event_based_hold = _scalar_property("defaultEventBasedHold") 

2523 """Are uploaded objects automatically placed under an even-based hold? 

2524 

2525 If True, uploaded objects will be placed under an event-based hold to 

2526 be released at a future time. When released an object will then begin 

2527 the retention period determined by the policy retention period for the 

2528 object bucket. 

2529 

2530 See https://cloud.google.com/storage/docs/json_api/v1/buckets 

2531 

2532 If the property is not set locally, returns ``None``. 

2533 

2534 :rtype: bool or ``NoneType`` 

2535 """ 

2536 

2537 @property 

2538 def default_kms_key_name(self): 

2539 """Retrieve / set default KMS encryption key for objects in the bucket. 

2540 

2541 See https://cloud.google.com/storage/docs/json_api/v1/buckets 

2542 

2543 :setter: Set default KMS encryption key for items in this bucket. 

2544 :getter: Get default KMS encryption key for items in this bucket. 

2545 

2546 :rtype: str 

2547 :returns: Default KMS encryption key, or ``None`` if not set. 

2548 """ 

2549 encryption_config = self._properties.get("encryption", {}) 

2550 return encryption_config.get("defaultKmsKeyName") 

2551 

2552 @default_kms_key_name.setter 

2553 def default_kms_key_name(self, value): 

2554 """Set default KMS encryption key for objects in the bucket. 

2555 

2556 :type value: str or None 

2557 :param value: new KMS key name (None to clear any existing key). 

2558 """ 

2559 encryption_config = self._properties.get("encryption", {}) 

2560 encryption_config["defaultKmsKeyName"] = value 

2561 self._patch_property("encryption", encryption_config) 

2562 

2563 @property 

2564 def labels(self): 

2565 """Retrieve or set labels assigned to this bucket. 

2566 

2567 See 

2568 https://cloud.google.com/storage/docs/json_api/v1/buckets#labels 

2569 

2570 .. note:: 

2571 

2572 The getter for this property returns a dict which is a *copy* 

2573 of the bucket's labels. Mutating that dict has no effect unless 

2574 you then re-assign the dict via the setter. E.g.: 

2575 

2576 >>> labels = bucket.labels 

2577 >>> labels['new_key'] = 'some-label' 

2578 >>> del labels['old_key'] 

2579 >>> bucket.labels = labels 

2580 >>> bucket.update() 

2581 

2582 :setter: Set labels for this bucket. 

2583 :getter: Gets the labels for this bucket. 

2584 

2585 :rtype: :class:`dict` 

2586 :returns: Name-value pairs (string->string) labelling the bucket. 

2587 """ 

2588 labels = self._properties.get("labels") 

2589 if labels is None: 

2590 return {} 

2591 return copy.deepcopy(labels) 

2592 

2593 @labels.setter 

2594 def labels(self, mapping): 

2595 """Set labels assigned to this bucket. 

2596 

2597 See 

2598 https://cloud.google.com/storage/docs/json_api/v1/buckets#labels 

2599 

2600 :type mapping: :class:`dict` 

2601 :param mapping: Name-value pairs (string->string) labelling the bucket. 

2602 """ 

2603 # If any labels have been expressly removed, we need to track this 

2604 # so that a future .patch() call can do the correct thing. 

2605 existing = set([k for k in self.labels.keys()]) 

2606 incoming = set([k for k in mapping.keys()]) 

2607 self._label_removals = self._label_removals.union(existing.difference(incoming)) 

2608 mapping = {k: str(v) for k, v in mapping.items()} 

2609 

2610 # Actually update the labels on the object. 

2611 self._patch_property("labels", copy.deepcopy(mapping)) 

2612 

2613 @property 

2614 def etag(self): 

2615 """Retrieve the ETag for the bucket. 

2616 

2617 See https://tools.ietf.org/html/rfc2616#section-3.11 and 

2618 https://cloud.google.com/storage/docs/json_api/v1/buckets 

2619 

2620 :rtype: str or ``NoneType`` 

2621 :returns: The bucket etag or ``None`` if the bucket's 

2622 resource has not been loaded from the server. 

2623 """ 

2624 return self._properties.get("etag") 

2625 

2626 @property 

2627 def id(self): 

2628 """Retrieve the ID for the bucket. 

2629 

2630 See https://cloud.google.com/storage/docs/json_api/v1/buckets 

2631 

2632 :rtype: str or ``NoneType`` 

2633 :returns: The ID of the bucket or ``None`` if the bucket's 

2634 resource has not been loaded from the server. 

2635 """ 

2636 return self._properties.get("id") 

2637 

2638 @property 

2639 def iam_configuration(self): 

2640 """Retrieve IAM configuration for this bucket. 

2641 

2642 :rtype: :class:`IAMConfiguration` 

2643 :returns: an instance for managing the bucket's IAM configuration. 

2644 """ 

2645 info = self._properties.get("iamConfiguration", {}) 

2646 return IAMConfiguration.from_api_repr(info, self) 

2647 

2648 @property 

2649 def soft_delete_policy(self): 

2650 """Retrieve the soft delete policy for this bucket. 

2651 

2652 See https://cloud.google.com/storage/docs/soft-delete 

2653 

2654 :rtype: :class:`SoftDeletePolicy` 

2655 :returns: an instance for managing the bucket's soft delete policy. 

2656 """ 

2657 policy = self._properties.get("softDeletePolicy", {}) 

2658 return SoftDeletePolicy.from_api_repr(policy, self) 

2659 

2660 @property 

2661 def lifecycle_rules(self): 

2662 """Retrieve or set lifecycle rules configured for this bucket. 

2663 

2664 See https://cloud.google.com/storage/docs/lifecycle and 

2665 https://cloud.google.com/storage/docs/json_api/v1/buckets 

2666 

2667 .. note:: 

2668 

2669 The getter for this property returns a generator which yields 

2670 *copies* of the bucket's lifecycle rules mappings. Mutating the 

2671 output dicts has no effect unless you then re-assign the dict via 

2672 the setter. E.g.: 

2673 

2674 >>> rules = list(bucket.lifecycle_rules) 

2675 >>> rules.append({'origin': '/foo', ...}) 

2676 >>> rules[1]['rule']['action']['type'] = 'Delete' 

2677 >>> del rules[0] 

2678 >>> bucket.lifecycle_rules = rules 

2679 >>> bucket.update() 

2680 

2681 :setter: Set lifecycle rules for this bucket. 

2682 :getter: Gets the lifecycle rules for this bucket. 

2683 

2684 :rtype: generator(dict) 

2685 :returns: A sequence of mappings describing each lifecycle rule. 

2686 """ 

2687 info = self._properties.get("lifecycle", {}) 

2688 for rule in info.get("rule", ()): 

2689 action_type = rule["action"]["type"] 

2690 if action_type == "Delete": 

2691 yield LifecycleRuleDelete.from_api_repr(rule) 

2692 elif action_type == "SetStorageClass": 

2693 yield LifecycleRuleSetStorageClass.from_api_repr(rule) 

2694 elif action_type == "AbortIncompleteMultipartUpload": 

2695 yield LifecycleRuleAbortIncompleteMultipartUpload.from_api_repr(rule) 

2696 else: 

2697 warnings.warn( 

2698 "Unknown lifecycle rule type received: {}. Please upgrade to the latest version of google-cloud-storage.".format( 

2699 rule 

2700 ), 

2701 UserWarning, 

2702 stacklevel=1, 

2703 ) 

2704 

2705 @lifecycle_rules.setter 

2706 def lifecycle_rules(self, rules): 

2707 """Set lifecycle rules configured for this bucket. 

2708 

2709 See https://cloud.google.com/storage/docs/lifecycle and 

2710 https://cloud.google.com/storage/docs/json_api/v1/buckets 

2711 

2712 :type rules: list of dictionaries 

2713 :param rules: A sequence of mappings describing each lifecycle rule. 

2714 """ 

2715 rules = [dict(rule) for rule in rules] # Convert helpers if needed 

2716 self._patch_property("lifecycle", {"rule": rules}) 

2717 

2718 def clear_lifecycle_rules(self): 

2719 """Clear lifecycle rules configured for this bucket. 

2720 

2721 See https://cloud.google.com/storage/docs/lifecycle and 

2722 https://cloud.google.com/storage/docs/json_api/v1/buckets 

2723 """ 

2724 self.lifecycle_rules = [] 

2725 

2726 def clear_lifecyle_rules(self): 

2727 """Deprecated alias for clear_lifecycle_rules.""" 

2728 return self.clear_lifecycle_rules() 

2729 

2730 def add_lifecycle_delete_rule(self, **kw): 

2731 """Add a "delete" rule to lifecycle rules configured for this bucket. 

2732 

2733 This defines a [lifecycle configuration](https://cloud.google.com/storage/docs/lifecycle), 

2734 which is set on the bucket. For the general format of a lifecycle configuration, see the 

2735 [bucket resource representation for JSON](https://cloud.google.com/storage/docs/json_api/v1/buckets). 

2736 See also a [code sample](https://cloud.google.com/storage/docs/samples/storage-enable-bucket-lifecycle-management#storage_enable_bucket_lifecycle_management-python). 

2737 

2738 :type kw: dict 

2739 :params kw: arguments passed to :class:`LifecycleRuleConditions`. 

2740 """ 

2741 rules = list(self.lifecycle_rules) 

2742 rules.append(LifecycleRuleDelete(**kw)) 

2743 self.lifecycle_rules = rules 

2744 

2745 def add_lifecycle_set_storage_class_rule(self, storage_class, **kw): 

2746 """Add a "set storage class" rule to lifecycle rules. 

2747 

2748 This defines a [lifecycle configuration](https://cloud.google.com/storage/docs/lifecycle), 

2749 which is set on the bucket. For the general format of a lifecycle configuration, see the 

2750 [bucket resource representation for JSON](https://cloud.google.com/storage/docs/json_api/v1/buckets). 

2751 

2752 :type storage_class: str, one of :attr:`STORAGE_CLASSES`. 

2753 :param storage_class: new storage class to assign to matching items. 

2754 

2755 :type kw: dict 

2756 :params kw: arguments passed to :class:`LifecycleRuleConditions`. 

2757 """ 

2758 rules = list(self.lifecycle_rules) 

2759 rules.append(LifecycleRuleSetStorageClass(storage_class, **kw)) 

2760 self.lifecycle_rules = rules 

2761 

2762 def add_lifecycle_abort_incomplete_multipart_upload_rule(self, **kw): 

2763 """Add a "abort incomplete multipart upload" rule to lifecycle rules. 

2764 

2765 .. note:: 

2766 The "age" lifecycle condition is the only supported condition 

2767 for this rule. 

2768 

2769 This defines a [lifecycle configuration](https://cloud.google.com/storage/docs/lifecycle), 

2770 which is set on the bucket. For the general format of a lifecycle configuration, see the 

2771 [bucket resource representation for JSON](https://cloud.google.com/storage/docs/json_api/v1/buckets). 

2772 

2773 :type kw: dict 

2774 :params kw: arguments passed to :class:`LifecycleRuleConditions`. 

2775 """ 

2776 rules = list(self.lifecycle_rules) 

2777 rules.append(LifecycleRuleAbortIncompleteMultipartUpload(**kw)) 

2778 self.lifecycle_rules = rules 

2779 

2780 _location = _scalar_property("location") 

2781 

2782 @property 

2783 def location(self): 

2784 """Retrieve location configured for this bucket. 

2785 

2786 See https://cloud.google.com/storage/docs/json_api/v1/buckets and 

2787 https://cloud.google.com/storage/docs/locations 

2788 

2789 Returns ``None`` if the property has not been set before creation, 

2790 or if the bucket's resource has not been loaded from the server. 

2791 :rtype: str or ``NoneType`` 

2792 """ 

2793 return self._location 

2794 

2795 @location.setter 

2796 def location(self, value): 

2797 """(Deprecated) Set `Bucket.location` 

2798 

2799 This can only be set at bucket **creation** time. 

2800 

2801 See https://cloud.google.com/storage/docs/json_api/v1/buckets and 

2802 https://cloud.google.com/storage/docs/bucket-locations 

2803 

2804 .. warning:: 

2805 

2806 Assignment to 'Bucket.location' is deprecated, as it is only 

2807 valid before the bucket is created. Instead, pass the location 

2808 to `Bucket.create`. 

2809 """ 

2810 warnings.warn(_LOCATION_SETTER_MESSAGE, DeprecationWarning, stacklevel=2) 

2811 self._location = value 

2812 

2813 @property 

2814 def data_locations(self): 

2815 """Retrieve the list of regional locations for custom dual-region buckets. 

2816 

2817 See https://cloud.google.com/storage/docs/json_api/v1/buckets and 

2818 https://cloud.google.com/storage/docs/locations 

2819 

2820 Returns ``None`` if the property has not been set before creation, 

2821 if the bucket's resource has not been loaded from the server, 

2822 or if the bucket is not a dual-regions bucket. 

2823 :rtype: list of str or ``NoneType`` 

2824 """ 

2825 custom_placement_config = self._properties.get("customPlacementConfig", {}) 

2826 return custom_placement_config.get("dataLocations") 

2827 

2828 @property 

2829 def location_type(self): 

2830 """Retrieve the location type for the bucket. 

2831 

2832 See https://cloud.google.com/storage/docs/storage-classes 

2833 

2834 :getter: Gets the the location type for this bucket. 

2835 

2836 :rtype: str or ``NoneType`` 

2837 :returns: 

2838 If set, one of 

2839 :attr:`~google.cloud.storage.constants.MULTI_REGION_LOCATION_TYPE`, 

2840 :attr:`~google.cloud.storage.constants.REGION_LOCATION_TYPE`, or 

2841 :attr:`~google.cloud.storage.constants.DUAL_REGION_LOCATION_TYPE`, 

2842 else ``None``. 

2843 """ 

2844 return self._properties.get("locationType") 

2845 

2846 def get_logging(self): 

2847 """Return info about access logging for this bucket. 

2848 

2849 See https://cloud.google.com/storage/docs/access-logs#status 

2850 

2851 :rtype: dict or None 

2852 :returns: a dict w/ keys, ``logBucket`` and ``logObjectPrefix`` 

2853 (if logging is enabled), or None (if not). 

2854 """ 

2855 info = self._properties.get("logging") 

2856 return copy.deepcopy(info) 

2857 

2858 def enable_logging(self, bucket_name, object_prefix=""): 

2859 """Enable access logging for this bucket. 

2860 

2861 See https://cloud.google.com/storage/docs/access-logs 

2862 

2863 :type bucket_name: str 

2864 :param bucket_name: name of bucket in which to store access logs 

2865 

2866 :type object_prefix: str 

2867 :param object_prefix: prefix for access log filenames 

2868 """ 

2869 info = {"logBucket": bucket_name, "logObjectPrefix": object_prefix} 

2870 self._patch_property("logging", info) 

2871 

2872 def disable_logging(self): 

2873 """Disable access logging for this bucket. 

2874 

2875 See https://cloud.google.com/storage/docs/access-logs#disabling 

2876 """ 

2877 self._patch_property("logging", None) 

2878 

2879 @property 

2880 def metageneration(self): 

2881 """Retrieve the metageneration for the bucket. 

2882 

2883 See https://cloud.google.com/storage/docs/json_api/v1/buckets 

2884 

2885 :rtype: int or ``NoneType`` 

2886 :returns: The metageneration of the bucket or ``None`` if the bucket's 

2887 resource has not been loaded from the server. 

2888 """ 

2889 metageneration = self._properties.get("metageneration") 

2890 if metageneration is not None: 

2891 return int(metageneration) 

2892 

2893 @property 

2894 def owner(self): 

2895 """Retrieve info about the owner of the bucket. 

2896 

2897 See https://cloud.google.com/storage/docs/json_api/v1/buckets 

2898 

2899 :rtype: dict or ``NoneType`` 

2900 :returns: Mapping of owner's role/ID. Returns ``None`` if the bucket's 

2901 resource has not been loaded from the server. 

2902 """ 

2903 return copy.deepcopy(self._properties.get("owner")) 

2904 

2905 @property 

2906 def project_number(self): 

2907 """Retrieve the number of the project to which the bucket is assigned. 

2908 

2909 See https://cloud.google.com/storage/docs/json_api/v1/buckets 

2910 

2911 :rtype: int or ``NoneType`` 

2912 :returns: The project number that owns the bucket or ``None`` if 

2913 the bucket's resource has not been loaded from the server. 

2914 """ 

2915 project_number = self._properties.get("projectNumber") 

2916 if project_number is not None: 

2917 return int(project_number) 

2918 

2919 @property 

2920 def retention_policy_effective_time(self): 

2921 """Retrieve the effective time of the bucket's retention policy. 

2922 

2923 :rtype: datetime.datetime or ``NoneType`` 

2924 :returns: point-in time at which the bucket's retention policy is 

2925 effective, or ``None`` if the property is not 

2926 set locally. 

2927 """ 

2928 policy = self._properties.get("retentionPolicy") 

2929 if policy is not None: 

2930 timestamp = policy.get("effectiveTime") 

2931 if timestamp is not None: 

2932 return _rfc3339_nanos_to_datetime(timestamp) 

2933 

2934 @property 

2935 def retention_policy_locked(self): 

2936 """Retrieve whthere the bucket's retention policy is locked. 

2937 

2938 :rtype: bool 

2939 :returns: True if the bucket's policy is locked, or else False 

2940 if the policy is not locked, or the property is not 

2941 set locally. 

2942 """ 

2943 policy = self._properties.get("retentionPolicy") 

2944 if policy is not None: 

2945 return policy.get("isLocked") 

2946 

2947 @property 

2948 def retention_period(self): 

2949 """Retrieve or set the retention period for items in the bucket. 

2950 

2951 :rtype: int or ``NoneType`` 

2952 :returns: number of seconds to retain items after upload or release 

2953 from event-based lock, or ``None`` if the property is not 

2954 set locally. 

2955 """ 

2956 policy = self._properties.get("retentionPolicy") 

2957 if policy is not None: 

2958 period = policy.get("retentionPeriod") 

2959 if period is not None: 

2960 return int(period) 

2961 

2962 @retention_period.setter 

2963 def retention_period(self, value): 

2964 """Set the retention period for items in the bucket. 

2965 

2966 :type value: int 

2967 :param value: 

2968 number of seconds to retain items after upload or release from 

2969 event-based lock. 

2970 

2971 :raises ValueError: if the bucket's retention policy is locked. 

2972 """ 

2973 policy = self._properties.setdefault("retentionPolicy", {}) 

2974 if value is not None: 

2975 policy["retentionPeriod"] = str(value) 

2976 else: 

2977 policy = None 

2978 self._patch_property("retentionPolicy", policy) 

2979 

2980 @property 

2981 def self_link(self): 

2982 """Retrieve the URI for the bucket. 

2983 

2984 See https://cloud.google.com/storage/docs/json_api/v1/buckets 

2985 

2986 :rtype: str or ``NoneType`` 

2987 :returns: The self link for the bucket or ``None`` if 

2988 the bucket's resource has not been loaded from the server. 

2989 """ 

2990 return self._properties.get("selfLink") 

2991 

2992 @property 

2993 def storage_class(self): 

2994 """Retrieve or set the storage class for the bucket. 

2995 

2996 See https://cloud.google.com/storage/docs/storage-classes 

2997 

2998 :setter: Set the storage class for this bucket. 

2999 :getter: Gets the the storage class for this bucket. 

3000 

3001 :rtype: str or ``NoneType`` 

3002 :returns: 

3003 If set, one of 

3004 :attr:`~google.cloud.storage.constants.NEARLINE_STORAGE_CLASS`, 

3005 :attr:`~google.cloud.storage.constants.COLDLINE_STORAGE_CLASS`, 

3006 :attr:`~google.cloud.storage.constants.ARCHIVE_STORAGE_CLASS`, 

3007 :attr:`~google.cloud.storage.constants.STANDARD_STORAGE_CLASS`, 

3008 :attr:`~google.cloud.storage.constants.MULTI_REGIONAL_LEGACY_STORAGE_CLASS`, 

3009 :attr:`~google.cloud.storage.constants.REGIONAL_LEGACY_STORAGE_CLASS`, 

3010 or 

3011 :attr:`~google.cloud.storage.constants.DURABLE_REDUCED_AVAILABILITY_LEGACY_STORAGE_CLASS`, 

3012 else ``None``. 

3013 """ 

3014 return self._properties.get("storageClass") 

3015 

3016 @storage_class.setter 

3017 def storage_class(self, value): 

3018 """Set the storage class for the bucket. 

3019 

3020 See https://cloud.google.com/storage/docs/storage-classes 

3021 

3022 :type value: str 

3023 :param value: 

3024 One of 

3025 :attr:`~google.cloud.storage.constants.NEARLINE_STORAGE_CLASS`, 

3026 :attr:`~google.cloud.storage.constants.COLDLINE_STORAGE_CLASS`, 

3027 :attr:`~google.cloud.storage.constants.ARCHIVE_STORAGE_CLASS`, 

3028 :attr:`~google.cloud.storage.constants.STANDARD_STORAGE_CLASS`, 

3029 :attr:`~google.cloud.storage.constants.MULTI_REGIONAL_LEGACY_STORAGE_CLASS`, 

3030 :attr:`~google.cloud.storage.constants.REGIONAL_LEGACY_STORAGE_CLASS`, 

3031 or 

3032 :attr:`~google.cloud.storage.constants.DURABLE_REDUCED_AVAILABILITY_LEGACY_STORAGE_CLASS`, 

3033 """ 

3034 self._patch_property("storageClass", value) 

3035 

3036 @property 

3037 def time_created(self): 

3038 """Retrieve the timestamp at which the bucket was created. 

3039 

3040 See https://cloud.google.com/storage/docs/json_api/v1/buckets 

3041 

3042 :rtype: :class:`datetime.datetime` or ``NoneType`` 

3043 :returns: Datetime object parsed from RFC3339 valid timestamp, or 

3044 ``None`` if the bucket's resource has not been loaded 

3045 from the server. 

3046 """ 

3047 value = self._properties.get("timeCreated") 

3048 if value is not None: 

3049 return _rfc3339_nanos_to_datetime(value) 

3050 

3051 @property 

3052 def updated(self): 

3053 """Retrieve the timestamp at which the bucket was last updated. 

3054 

3055 See https://cloud.google.com/storage/docs/json_api/v1/buckets 

3056 

3057 :rtype: :class:`datetime.datetime` or ``NoneType`` 

3058 :returns: Datetime object parsed from RFC3339 valid timestamp, or 

3059 ``None`` if the bucket's resource has not been loaded 

3060 from the server. 

3061 """ 

3062 value = self._properties.get("updated") 

3063 if value is not None: 

3064 return _rfc3339_nanos_to_datetime(value) 

3065 

3066 @property 

3067 def versioning_enabled(self): 

3068 """Is versioning enabled for this bucket? 

3069 

3070 See https://cloud.google.com/storage/docs/object-versioning for 

3071 details. 

3072 

3073 :setter: Update whether versioning is enabled for this bucket. 

3074 :getter: Query whether versioning is enabled for this bucket. 

3075 

3076 :rtype: bool 

3077 :returns: True if enabled, else False. 

3078 """ 

3079 versioning = self._properties.get("versioning", {}) 

3080 return versioning.get("enabled", False) 

3081 

3082 @versioning_enabled.setter 

3083 def versioning_enabled(self, value): 

3084 """Enable versioning for this bucket. 

3085 

3086 See https://cloud.google.com/storage/docs/object-versioning for 

3087 details. 

3088 

3089 :type value: convertible to boolean 

3090 :param value: should versioning be enabled for the bucket? 

3091 """ 

3092 self._patch_property("versioning", {"enabled": bool(value)}) 

3093 

3094 @property 

3095 def requester_pays(self): 

3096 """Does the requester pay for API requests for this bucket? 

3097 

3098 See https://cloud.google.com/storage/docs/requester-pays for 

3099 details. 

3100 

3101 :setter: Update whether requester pays for this bucket. 

3102 :getter: Query whether requester pays for this bucket. 

3103 

3104 :rtype: bool 

3105 :returns: True if requester pays for API requests for the bucket, 

3106 else False. 

3107 """ 

3108 versioning = self._properties.get("billing", {}) 

3109 return versioning.get("requesterPays", False) 

3110 

3111 @requester_pays.setter 

3112 def requester_pays(self, value): 

3113 """Update whether requester pays for API requests for this bucket. 

3114 

3115 See https://cloud.google.com/storage/docs/using-requester-pays for 

3116 details. 

3117 

3118 :type value: convertible to boolean 

3119 :param value: should requester pay for API requests for the bucket? 

3120 """ 

3121 self._patch_property("billing", {"requesterPays": bool(value)}) 

3122 

3123 @property 

3124 def autoclass_enabled(self): 

3125 """Whether Autoclass is enabled for this bucket. 

3126 

3127 See https://cloud.google.com/storage/docs/using-autoclass for details. 

3128 

3129 :setter: Update whether autoclass is enabled for this bucket. 

3130 :getter: Query whether autoclass is enabled for this bucket. 

3131 

3132 :rtype: bool 

3133 :returns: True if enabled, else False. 

3134 """ 

3135 autoclass = self._properties.get("autoclass", {}) 

3136 return autoclass.get("enabled", False) 

3137 

3138 @autoclass_enabled.setter 

3139 def autoclass_enabled(self, value): 

3140 """Enable or disable Autoclass at the bucket-level. 

3141 

3142 See https://cloud.google.com/storage/docs/using-autoclass for details. 

3143 

3144 :type value: convertible to boolean 

3145 :param value: If true, enable Autoclass for this bucket. 

3146 If false, disable Autoclass for this bucket. 

3147 """ 

3148 autoclass = self._properties.get("autoclass", {}) 

3149 autoclass["enabled"] = bool(value) 

3150 self._patch_property("autoclass", autoclass) 

3151 

3152 @property 

3153 def autoclass_toggle_time(self): 

3154 """Retrieve the toggle time when Autoclaass was last enabled or disabled for the bucket. 

3155 :rtype: datetime.datetime or ``NoneType`` 

3156 :returns: point-in time at which the bucket's autoclass is toggled, or ``None`` if the property is not set locally. 

3157 """ 

3158 autoclass = self._properties.get("autoclass") 

3159 if autoclass is not None: 

3160 timestamp = autoclass.get("toggleTime") 

3161 if timestamp is not None: 

3162 return _rfc3339_nanos_to_datetime(timestamp) 

3163 

3164 @property 

3165 def autoclass_terminal_storage_class(self): 

3166 """The storage class that objects in an Autoclass bucket eventually transition to if 

3167 they are not read for a certain length of time. Valid values are NEARLINE and ARCHIVE. 

3168 

3169 See https://cloud.google.com/storage/docs/using-autoclass for details. 

3170 

3171 :setter: Set the terminal storage class for Autoclass configuration. 

3172 :getter: Get the terminal storage class for Autoclass configuration. 

3173 

3174 :rtype: str 

3175 :returns: The terminal storage class if Autoclass is enabled, else ``None``. 

3176 """ 

3177 autoclass = self._properties.get("autoclass", {}) 

3178 return autoclass.get("terminalStorageClass", None) 

3179 

3180 @autoclass_terminal_storage_class.setter 

3181 def autoclass_terminal_storage_class(self, value): 

3182 """The storage class that objects in an Autoclass bucket eventually transition to if 

3183 they are not read for a certain length of time. Valid values are NEARLINE and ARCHIVE. 

3184 

3185 See https://cloud.google.com/storage/docs/using-autoclass for details. 

3186 

3187 :type value: str 

3188 :param value: The only valid values are `"NEARLINE"` and `"ARCHIVE"`. 

3189 """ 

3190 autoclass = self._properties.get("autoclass", {}) 

3191 autoclass["terminalStorageClass"] = value 

3192 self._patch_property("autoclass", autoclass) 

3193 

3194 @property 

3195 def autoclass_terminal_storage_class_update_time(self): 

3196 """The time at which the Autoclass terminal_storage_class field was last updated for this bucket 

3197 :rtype: datetime.datetime or ``NoneType`` 

3198 :returns: point-in time at which the bucket's terminal_storage_class is last updated, or ``None`` if the property is not set locally. 

3199 """ 

3200 autoclass = self._properties.get("autoclass") 

3201 if autoclass is not None: 

3202 timestamp = autoclass.get("terminalStorageClassUpdateTime") 

3203 if timestamp is not None: 

3204 return _rfc3339_nanos_to_datetime(timestamp) 

3205 

3206 @property 

3207 def object_retention_mode(self): 

3208 """Retrieve the object retention mode set on the bucket. 

3209 

3210 :rtype: str 

3211 :returns: When set to Enabled, retention configurations can be 

3212 set on objects in the bucket. 

3213 """ 

3214 object_retention = self._properties.get("objectRetention") 

3215 if object_retention is not None: 

3216 return object_retention.get("mode") 

3217 

3218 @property 

3219 def hierarchical_namespace_enabled(self): 

3220 """Whether hierarchical namespace is enabled for this bucket. 

3221 

3222 :setter: Update whether hierarchical namespace is enabled for this bucket. 

3223 :getter: Query whether hierarchical namespace is enabled for this bucket. 

3224 

3225 :rtype: bool 

3226 :returns: True if enabled, else False. 

3227 """ 

3228 hns = self._properties.get("hierarchicalNamespace", {}) 

3229 return hns.get("enabled") 

3230 

3231 @hierarchical_namespace_enabled.setter 

3232 def hierarchical_namespace_enabled(self, value): 

3233 """Enable or disable hierarchical namespace at the bucket-level. 

3234 

3235 :type value: convertible to boolean 

3236 :param value: If true, enable hierarchical namespace for this bucket. 

3237 If false, disable hierarchical namespace for this bucket. 

3238 

3239 .. note:: 

3240 To enable hierarchical namespace, you must set it at bucket creation time. 

3241 Currently, hierarchical namespace configuration cannot be changed after bucket creation. 

3242 """ 

3243 hns = self._properties.get("hierarchicalNamespace", {}) 

3244 hns["enabled"] = bool(value) 

3245 self._patch_property("hierarchicalNamespace", hns) 

3246 

3247 def configure_website(self, main_page_suffix=None, not_found_page=None): 

3248 """Configure website-related properties. 

3249 

3250 See https://cloud.google.com/storage/docs/static-website 

3251 

3252 .. note:: 

3253 This configures the bucket's website-related properties,controlling how 

3254 the service behaves when accessing bucket contents as a web site. 

3255 See [tutorials](https://cloud.google.com/storage/docs/hosting-static-website) and 

3256 [code samples](https://cloud.google.com/storage/docs/samples/storage-define-bucket-website-configuration#storage_define_bucket_website_configuration-python) 

3257 for more information. 

3258 

3259 :type main_page_suffix: str 

3260 :param main_page_suffix: The page to use as the main page 

3261 of a directory. 

3262 Typically something like index.html. 

3263 

3264 :type not_found_page: str 

3265 :param not_found_page: The file to use when a page isn't found. 

3266 """ 

3267 data = { 

3268 "mainPageSuffix": main_page_suffix, 

3269 "notFoundPage": not_found_page, 

3270 } 

3271 self._patch_property("website", data) 

3272 

3273 def disable_website(self): 

3274 """Disable the website configuration for this bucket. 

3275 

3276 This is really just a shortcut for setting the website-related 

3277 attributes to ``None``. 

3278 """ 

3279 return self.configure_website(None, None) 

3280 

3281 def get_iam_policy( 

3282 self, 

3283 client=None, 

3284 requested_policy_version=None, 

3285 timeout=_DEFAULT_TIMEOUT, 

3286 retry=DEFAULT_RETRY, 

3287 ): 

3288 """Retrieve the IAM policy for the bucket. 

3289 

3290 See [API reference docs](https://cloud.google.com/storage/docs/json_api/v1/buckets/getIamPolicy) 

3291 and a [code sample](https://cloud.google.com/storage/docs/samples/storage-view-bucket-iam-members#storage_view_bucket_iam_members-python). 

3292 

3293 If :attr:`user_project` is set, bills the API request to that project. 

3294 

3295 :type client: :class:`~google.cloud.storage.client.Client` or 

3296 ``NoneType`` 

3297 :param client: (Optional) The client to use. If not passed, falls back 

3298 to the ``client`` stored on the current bucket. 

3299 

3300 :type requested_policy_version: int or ``NoneType`` 

3301 :param requested_policy_version: (Optional) The version of IAM policies to request. 

3302 If a policy with a condition is requested without 

3303 setting this, the server will return an error. 

3304 This must be set to a value of 3 to retrieve IAM 

3305 policies containing conditions. This is to prevent 

3306 client code that isn't aware of IAM conditions from 

3307 interpreting and modifying policies incorrectly. 

3308 The service might return a policy with version lower 

3309 than the one that was requested, based on the 

3310 feature syntax in the policy fetched. 

3311 

3312 :type timeout: float or tuple 

3313 :param timeout: 

3314 (Optional) The amount of time, in seconds, to wait 

3315 for the server response. See: :ref:`configuring_timeouts` 

3316 

3317 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

3318 :param retry: 

3319 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

3320 

3321 :rtype: :class:`google.api_core.iam.Policy` 

3322 :returns: the policy instance, based on the resource returned from 

3323 the ``getIamPolicy`` API request. 

3324 """ 

3325 with create_trace_span(name="Storage.Bucket.getIamPolicy"): 

3326 client = self._require_client(client) 

3327 query_params = {} 

3328 

3329 if self.user_project is not None: 

3330 query_params["userProject"] = self.user_project 

3331 

3332 if requested_policy_version is not None: 

3333 query_params["optionsRequestedPolicyVersion"] = requested_policy_version 

3334 

3335 info = client._get_resource( 

3336 f"{self.path}/iam", 

3337 query_params=query_params, 

3338 timeout=timeout, 

3339 retry=retry, 

3340 _target_object=None, 

3341 ) 

3342 return Policy.from_api_repr(info) 

3343 

3344 def set_iam_policy( 

3345 self, 

3346 policy, 

3347 client=None, 

3348 timeout=_DEFAULT_TIMEOUT, 

3349 retry=DEFAULT_RETRY_IF_ETAG_IN_JSON, 

3350 ): 

3351 """Update the IAM policy for the bucket. 

3352 

3353 See 

3354 https://cloud.google.com/storage/docs/json_api/v1/buckets/setIamPolicy 

3355 

3356 If :attr:`user_project` is set, bills the API request to that project. 

3357 

3358 :type policy: :class:`google.api_core.iam.Policy` 

3359 :param policy: policy instance used to update bucket's IAM policy. 

3360 

3361 :type client: :class:`~google.cloud.storage.client.Client` or 

3362 ``NoneType`` 

3363 :param client: (Optional) The client to use. If not passed, falls back 

3364 to the ``client`` stored on the current bucket. 

3365 

3366 :type timeout: float or tuple 

3367 :param timeout: 

3368 (Optional) The amount of time, in seconds, to wait 

3369 for the server response. See: :ref:`configuring_timeouts` 

3370 

3371 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

3372 :param retry: 

3373 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

3374 

3375 :rtype: :class:`google.api_core.iam.Policy` 

3376 :returns: the policy instance, based on the resource returned from 

3377 the ``setIamPolicy`` API request. 

3378 """ 

3379 with create_trace_span(name="Storage.Bucket.setIamPolicy"): 

3380 client = self._require_client(client) 

3381 query_params = {} 

3382 

3383 if self.user_project is not None: 

3384 query_params["userProject"] = self.user_project 

3385 

3386 path = f"{self.path}/iam" 

3387 resource = policy.to_api_repr() 

3388 resource["resourceId"] = self.path 

3389 

3390 info = client._put_resource( 

3391 path, 

3392 resource, 

3393 query_params=query_params, 

3394 timeout=timeout, 

3395 retry=retry, 

3396 _target_object=None, 

3397 ) 

3398 

3399 return Policy.from_api_repr(info) 

3400 

3401 def test_iam_permissions( 

3402 self, 

3403 permissions, 

3404 client=None, 

3405 timeout=_DEFAULT_TIMEOUT, 

3406 retry=DEFAULT_RETRY, 

3407 ): 

3408 """API call: test permissions 

3409 

3410 See 

3411 https://cloud.google.com/storage/docs/json_api/v1/buckets/testIamPermissions 

3412 

3413 If :attr:`user_project` is set, bills the API request to that project. 

3414 

3415 :type permissions: list of string 

3416 :param permissions: the permissions to check 

3417 

3418 :type client: :class:`~google.cloud.storage.client.Client` or 

3419 ``NoneType`` 

3420 :param client: (Optional) The client to use. If not passed, falls back 

3421 to the ``client`` stored on the current bucket. 

3422 

3423 :type timeout: float or tuple 

3424 :param timeout: 

3425 (Optional) The amount of time, in seconds, to wait 

3426 for the server response. See: :ref:`configuring_timeouts` 

3427 

3428 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

3429 :param retry: 

3430 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

3431 

3432 :rtype: list of string 

3433 :returns: the permissions returned by the ``testIamPermissions`` API 

3434 request. 

3435 """ 

3436 with create_trace_span(name="Storage.Bucket.testIamPermissions"): 

3437 client = self._require_client(client) 

3438 query_params = {"permissions": permissions} 

3439 

3440 if self.user_project is not None: 

3441 query_params["userProject"] = self.user_project 

3442 

3443 path = f"{self.path}/iam/testPermissions" 

3444 resp = client._get_resource( 

3445 path, 

3446 query_params=query_params, 

3447 timeout=timeout, 

3448 retry=retry, 

3449 _target_object=None, 

3450 ) 

3451 return resp.get("permissions", []) 

3452 

3453 def make_public( 

3454 self, 

3455 recursive=False, 

3456 future=False, 

3457 client=None, 

3458 timeout=_DEFAULT_TIMEOUT, 

3459 if_metageneration_match=None, 

3460 if_metageneration_not_match=None, 

3461 retry=DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED, 

3462 ): 

3463 """Update bucket's ACL, granting read access to anonymous users. 

3464 

3465 :type recursive: bool 

3466 :param recursive: If True, this will make all blobs inside the bucket 

3467 public as well. 

3468 

3469 :type future: bool 

3470 :param future: If True, this will make all objects created in the 

3471 future public as well. 

3472 

3473 :type client: :class:`~google.cloud.storage.client.Client` or 

3474 ``NoneType`` 

3475 :param client: (Optional) The client to use. If not passed, falls back 

3476 to the ``client`` stored on the current bucket. 

3477 :type timeout: float or tuple 

3478 :param timeout: 

3479 (Optional) The amount of time, in seconds, to wait 

3480 for the server response. See: :ref:`configuring_timeouts` 

3481 

3482 :type if_metageneration_match: long 

3483 :param if_metageneration_match: (Optional) Make the operation conditional on whether the 

3484 blob's current metageneration matches the given value. 

3485 

3486 :type if_metageneration_not_match: long 

3487 :param if_metageneration_not_match: (Optional) Make the operation conditional on whether the 

3488 blob's current metageneration does not match the given value. 

3489 

3490 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

3491 :param retry: 

3492 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

3493 

3494 :raises ValueError: 

3495 If ``recursive`` is True, and the bucket contains more than 256 

3496 blobs. This is to prevent extremely long runtime of this 

3497 method. For such buckets, iterate over the blobs returned by 

3498 :meth:`list_blobs` and call 

3499 :meth:`~google.cloud.storage.blob.Blob.make_public` 

3500 for each blob. 

3501 """ 

3502 with create_trace_span(name="Storage.Bucket.makePublic"): 

3503 self.acl.all().grant_read() 

3504 self.acl.save( 

3505 client=client, 

3506 timeout=timeout, 

3507 if_metageneration_match=if_metageneration_match, 

3508 if_metageneration_not_match=if_metageneration_not_match, 

3509 retry=retry, 

3510 ) 

3511 

3512 if future: 

3513 doa = self.default_object_acl 

3514 if not doa.loaded: 

3515 doa.reload(client=client, timeout=timeout) 

3516 doa.all().grant_read() 

3517 doa.save( 

3518 client=client, 

3519 timeout=timeout, 

3520 if_metageneration_match=if_metageneration_match, 

3521 if_metageneration_not_match=if_metageneration_not_match, 

3522 retry=retry, 

3523 ) 

3524 

3525 if recursive: 

3526 blobs = list( 

3527 self.list_blobs( 

3528 projection="full", 

3529 max_results=self._MAX_OBJECTS_FOR_ITERATION + 1, 

3530 client=client, 

3531 timeout=timeout, 

3532 ) 

3533 ) 

3534 if len(blobs) > self._MAX_OBJECTS_FOR_ITERATION: 

3535 message = ( 

3536 "Refusing to make public recursively with more than " 

3537 "%d objects. If you actually want to make every object " 

3538 "in this bucket public, iterate through the blobs " 

3539 "returned by 'Bucket.list_blobs()' and call " 

3540 "'make_public' on each one." 

3541 ) % (self._MAX_OBJECTS_FOR_ITERATION,) 

3542 raise ValueError(message) 

3543 

3544 for blob in blobs: 

3545 blob.acl.all().grant_read() 

3546 blob.acl.save( 

3547 client=client, 

3548 timeout=timeout, 

3549 ) 

3550 

3551 def make_private( 

3552 self, 

3553 recursive=False, 

3554 future=False, 

3555 client=None, 

3556 timeout=_DEFAULT_TIMEOUT, 

3557 if_metageneration_match=None, 

3558 if_metageneration_not_match=None, 

3559 retry=DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED, 

3560 ): 

3561 """Update bucket's ACL, revoking read access for anonymous users. 

3562 

3563 :type recursive: bool 

3564 :param recursive: If True, this will make all blobs inside the bucket 

3565 private as well. 

3566 

3567 :type future: bool 

3568 :param future: If True, this will make all objects created in the 

3569 future private as well. 

3570 

3571 :type client: :class:`~google.cloud.storage.client.Client` or 

3572 ``NoneType`` 

3573 :param client: (Optional) The client to use. If not passed, falls back 

3574 to the ``client`` stored on the current bucket. 

3575 

3576 :type timeout: float or tuple 

3577 :param timeout: 

3578 (Optional) The amount of time, in seconds, to wait 

3579 for the server response. See: :ref:`configuring_timeouts` 

3580 

3581 :type if_metageneration_match: long 

3582 :param if_metageneration_match: (Optional) Make the operation conditional on whether the 

3583 blob's current metageneration matches the given value. 

3584 :type if_metageneration_not_match: long 

3585 :param if_metageneration_not_match: (Optional) Make the operation conditional on whether the 

3586 blob's current metageneration does not match the given value. 

3587 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

3588 :param retry: 

3589 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

3590 

3591 :raises ValueError: 

3592 If ``recursive`` is True, and the bucket contains more than 256 

3593 blobs. This is to prevent extremely long runtime of this 

3594 method. For such buckets, iterate over the blobs returned by 

3595 :meth:`list_blobs` and call 

3596 :meth:`~google.cloud.storage.blob.Blob.make_private` 

3597 for each blob. 

3598 """ 

3599 with create_trace_span(name="Storage.Bucket.makePrivate"): 

3600 self.acl.all().revoke_read() 

3601 self.acl.save( 

3602 client=client, 

3603 timeout=timeout, 

3604 if_metageneration_match=if_metageneration_match, 

3605 if_metageneration_not_match=if_metageneration_not_match, 

3606 retry=retry, 

3607 ) 

3608 

3609 if future: 

3610 doa = self.default_object_acl 

3611 if not doa.loaded: 

3612 doa.reload(client=client, timeout=timeout) 

3613 doa.all().revoke_read() 

3614 doa.save( 

3615 client=client, 

3616 timeout=timeout, 

3617 if_metageneration_match=if_metageneration_match, 

3618 if_metageneration_not_match=if_metageneration_not_match, 

3619 retry=retry, 

3620 ) 

3621 

3622 if recursive: 

3623 blobs = list( 

3624 self.list_blobs( 

3625 projection="full", 

3626 max_results=self._MAX_OBJECTS_FOR_ITERATION + 1, 

3627 client=client, 

3628 timeout=timeout, 

3629 ) 

3630 ) 

3631 if len(blobs) > self._MAX_OBJECTS_FOR_ITERATION: 

3632 message = ( 

3633 "Refusing to make private recursively with more than " 

3634 "%d objects. If you actually want to make every object " 

3635 "in this bucket private, iterate through the blobs " 

3636 "returned by 'Bucket.list_blobs()' and call " 

3637 "'make_private' on each one." 

3638 ) % (self._MAX_OBJECTS_FOR_ITERATION,) 

3639 raise ValueError(message) 

3640 

3641 for blob in blobs: 

3642 blob.acl.all().revoke_read() 

3643 blob.acl.save(client=client, timeout=timeout) 

3644 

3645 def generate_upload_policy(self, conditions, expiration=None, client=None): 

3646 """Create a signed upload policy for uploading objects. 

3647 

3648 This method generates and signs a policy document. You can use 

3649 [`policy documents`](https://cloud.google.com/storage/docs/xml-api/post-object-forms) 

3650 to allow visitors to a website to upload files to 

3651 Google Cloud Storage without giving them direct write access. 

3652 See a [code sample](https://cloud.google.com/storage/docs/xml-api/post-object-forms#python). 

3653 

3654 :type expiration: datetime 

3655 :param expiration: (Optional) Expiration in UTC. If not specified, the 

3656 policy will expire in 1 hour. 

3657 

3658 :type conditions: list 

3659 :param conditions: A list of conditions as described in the 

3660 `policy documents` documentation. 

3661 

3662 :type client: :class:`~google.cloud.storage.client.Client` 

3663 :param client: (Optional) The client to use. If not passed, falls back 

3664 to the ``client`` stored on the current bucket. 

3665 

3666 :rtype: dict 

3667 :returns: A dictionary of (form field name, form field value) of form 

3668 fields that should be added to your HTML upload form in order 

3669 to attach the signature. 

3670 """ 

3671 client = self._require_client(client) 

3672 credentials = client._credentials 

3673 _signing.ensure_signed_credentials(credentials) 

3674 

3675 if expiration is None: 

3676 expiration = _NOW(_UTC).replace(tzinfo=None) + datetime.timedelta(hours=1) 

3677 

3678 conditions = conditions + [{"bucket": self.name}] 

3679 

3680 policy_document = { 

3681 "expiration": _datetime_to_rfc3339(expiration), 

3682 "conditions": conditions, 

3683 } 

3684 

3685 encoded_policy_document = base64.b64encode( 

3686 json.dumps(policy_document).encode("utf-8") 

3687 ) 

3688 signature = base64.b64encode(credentials.sign_bytes(encoded_policy_document)) 

3689 

3690 fields = { 

3691 "bucket": self.name, 

3692 "GoogleAccessId": credentials.signer_email, 

3693 "policy": encoded_policy_document.decode("utf-8"), 

3694 "signature": signature.decode("utf-8"), 

3695 } 

3696 

3697 return fields 

3698 

3699 def lock_retention_policy( 

3700 self, client=None, timeout=_DEFAULT_TIMEOUT, retry=DEFAULT_RETRY 

3701 ): 

3702 """Lock the bucket's retention policy. 

3703 

3704 :type client: :class:`~google.cloud.storage.client.Client` or 

3705 ``NoneType`` 

3706 :param client: (Optional) The client to use. If not passed, falls back 

3707 to the ``client`` stored on the blob's bucket. 

3708 

3709 :type timeout: float or tuple 

3710 :param timeout: 

3711 (Optional) The amount of time, in seconds, to wait 

3712 for the server response. See: :ref:`configuring_timeouts` 

3713 

3714 :type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy 

3715 :param retry: 

3716 (Optional) How to retry the RPC. See: :ref:`configuring_retries` 

3717 

3718 :raises ValueError: 

3719 if the bucket has no metageneration (i.e., new or never reloaded); 

3720 if the bucket has no retention policy assigned; 

3721 if the bucket's retention policy is already locked. 

3722 """ 

3723 with create_trace_span(name="Storage.Bucket.lockRetentionPolicy"): 

3724 if "metageneration" not in self._properties: 

3725 raise ValueError( 

3726 "Bucket has no retention policy assigned: try 'reload'?" 

3727 ) 

3728 

3729 policy = self._properties.get("retentionPolicy") 

3730 

3731 if policy is None: 

3732 raise ValueError( 

3733 "Bucket has no retention policy assigned: try 'reload'?" 

3734 ) 

3735 

3736 if policy.get("isLocked"): 

3737 raise ValueError("Bucket's retention policy is already locked.") 

3738 

3739 client = self._require_client(client) 

3740 

3741 query_params = {"ifMetagenerationMatch": self.metageneration} 

3742 

3743 if self.user_project is not None: 

3744 query_params["userProject"] = self.user_project 

3745 

3746 path = f"/b/{self.name}/lockRetentionPolicy" 

3747 api_response = client._post_resource( 

3748 path, 

3749 None, 

3750 query_params=query_params, 

3751 timeout=timeout, 

3752 retry=retry, 

3753 _target_object=self, 

3754 ) 

3755 self._set_properties(api_response) 

3756 

3757 def generate_signed_url( 

3758 self, 

3759 expiration=None, 

3760 api_access_endpoint=None, 

3761 method="GET", 

3762 headers=None, 

3763 query_parameters=None, 

3764 client=None, 

3765 credentials=None, 

3766 version=None, 

3767 virtual_hosted_style=False, 

3768 bucket_bound_hostname=None, 

3769 scheme="http", 

3770 ): 

3771 """Generates a signed URL for this bucket. 

3772 

3773 .. note:: 

3774 

3775 If you are on Google Compute Engine, you can't generate a signed 

3776 URL using GCE service account. If you'd like to be able to generate 

3777 a signed URL from GCE, you can use a standard service account from a 

3778 JSON file rather than a GCE service account. 

3779 

3780 If you have a bucket that you want to allow access to for a set 

3781 amount of time, you can use this method to generate a URL that 

3782 is only valid within a certain time period. 

3783 

3784 If ``bucket_bound_hostname`` is set as an argument of :attr:`api_access_endpoint`, 

3785 ``https`` works only if using a ``CDN``. 

3786 

3787 :type expiration: Union[Integer, datetime.datetime, datetime.timedelta] 

3788 :param expiration: Point in time when the signed URL should expire. If 

3789 a ``datetime`` instance is passed without an explicit 

3790 ``tzinfo`` set, it will be assumed to be ``UTC``. 

3791 

3792 :type api_access_endpoint: str 

3793 :param api_access_endpoint: (Optional) URI base, for instance 

3794 "https://storage.googleapis.com". If not specified, the client's 

3795 api_endpoint will be used. Incompatible with bucket_bound_hostname. 

3796 

3797 :type method: str 

3798 :param method: The HTTP verb that will be used when requesting the URL. 

3799 

3800 :type headers: dict 

3801 :param headers: 

3802 (Optional) Additional HTTP headers to be included as part of the 

3803 signed URLs. See: 

3804 https://cloud.google.com/storage/docs/xml-api/reference-headers 

3805 Requests using the signed URL *must* pass the specified header 

3806 (name and value) with each request for the URL. 

3807 

3808 :type query_parameters: dict 

3809 :param query_parameters: 

3810 (Optional) Additional query parameters to be included as part of the 

3811 signed URLs. See: 

3812 https://cloud.google.com/storage/docs/xml-api/reference-headers#query 

3813 

3814 :type client: :class:`~google.cloud.storage.client.Client` or 

3815 ``NoneType`` 

3816 :param client: (Optional) The client to use. If not passed, falls back 

3817 to the ``client`` stored on the blob's bucket. 

3818 

3819 :type credentials: :class:`google.auth.credentials.Credentials` or 

3820 :class:`NoneType` 

3821 :param credentials: The authorization credentials to attach to requests. 

3822 These credentials identify this application to the service. 

3823 If none are specified, the client will attempt to ascertain 

3824 the credentials from the environment. 

3825 

3826 :type version: str 

3827 :param version: (Optional) The version of signed credential to create. 

3828 Must be one of 'v2' | 'v4'. 

3829 

3830 :type virtual_hosted_style: bool 

3831 :param virtual_hosted_style: 

3832 (Optional) If true, then construct the URL relative the bucket's 

3833 virtual hostname, e.g., '<bucket-name>.storage.googleapis.com'. 

3834 Incompatible with bucket_bound_hostname. 

3835 

3836 :type bucket_bound_hostname: str 

3837 :param bucket_bound_hostname: 

3838 (Optional) If passed, then construct the URL relative to the bucket-bound hostname. 

3839 Value can be a bare or with scheme, e.g., 'example.com' or 'http://example.com'. 

3840 Incompatible with api_access_endpoint and virtual_hosted_style. 

3841 See: https://cloud.google.com/storage/docs/request-endpoints#cname 

3842 

3843 :type scheme: str 

3844 :param scheme: 

3845 (Optional) If ``bucket_bound_hostname`` is passed as a bare hostname, use 

3846 this value as the scheme. ``https`` will work only when using a CDN. 

3847 Defaults to ``"http"``. 

3848 

3849 :raises: :exc:`ValueError` when version is invalid or mutually exclusive arguments are used. 

3850 :raises: :exc:`TypeError` when expiration is not a valid type. 

3851 :raises: :exc:`AttributeError` if credentials is not an instance 

3852 of :class:`google.auth.credentials.Signing`. 

3853 

3854 :rtype: str 

3855 :returns: A signed URL you can use to access the resource 

3856 until expiration. 

3857 """ 

3858 if version is None: 

3859 version = "v2" 

3860 elif version not in ("v2", "v4"): 

3861 raise ValueError("'version' must be either 'v2' or 'v4'") 

3862 

3863 if ( 

3864 api_access_endpoint is not None or virtual_hosted_style 

3865 ) and bucket_bound_hostname: 

3866 raise ValueError( 

3867 "The bucket_bound_hostname argument is not compatible with " 

3868 "either api_access_endpoint or virtual_hosted_style." 

3869 ) 

3870 

3871 if api_access_endpoint is None: 

3872 client = self._require_client(client) 

3873 api_access_endpoint = client.api_endpoint 

3874 

3875 # If you are on Google Compute Engine, you can't generate a signed URL 

3876 # using GCE service account. 

3877 # See https://github.com/googleapis/google-auth-library-python/issues/50 

3878 if virtual_hosted_style: 

3879 api_access_endpoint = _virtual_hosted_style_base_url( 

3880 api_access_endpoint, self.name 

3881 ) 

3882 resource = "/" 

3883 elif bucket_bound_hostname: 

3884 api_access_endpoint = _bucket_bound_hostname_url( 

3885 bucket_bound_hostname, scheme 

3886 ) 

3887 resource = "/" 

3888 else: 

3889 resource = f"/{self.name}" 

3890 

3891 if credentials is None: 

3892 client = self._require_client(client) # May be redundant, but that's ok. 

3893 credentials = client._credentials 

3894 

3895 if version == "v2": 

3896 helper = generate_signed_url_v2 

3897 else: 

3898 helper = generate_signed_url_v4 

3899 

3900 return helper( 

3901 credentials, 

3902 resource=resource, 

3903 expiration=expiration, 

3904 api_access_endpoint=api_access_endpoint, 

3905 method=method.upper(), 

3906 headers=headers, 

3907 query_parameters=query_parameters, 

3908 ) 

3909 

3910 @property 

3911 def ip_filter(self): 

3912 """Retrieve or set the IP Filter configuration for this bucket. 

3913 

3914 See https://cloud.google.com/storage/docs/ip-filtering-overview and 

3915 https://cloud.google.com/storage/docs/json_api/v1/buckets#ipFilter 

3916 

3917 .. note:: 

3918 The getter for this property returns an 

3919 :class:`~google.cloud.storage.ip_filter.IPFilter` object, which is a 

3920 structured representation of the bucket's IP filter configuration. 

3921 Modifying the returned object has no effect. To update the bucket's 

3922 IP filter, create and assign a new ``IPFilter`` object to this 

3923 property and then call 

3924 :meth:`~google.cloud.storage.bucket.Bucket.patch`. 

3925 

3926 .. code-block:: python 

3927 

3928 from google.cloud.storage.ip_filter import ( 

3929 IPFilter, 

3930 PublicNetworkSource, 

3931 ) 

3932 

3933 ip_filter = IPFilter() 

3934 ip_filter.mode = "Enabled" 

3935 ip_filter.public_network_source = PublicNetworkSource( 

3936 allowed_ip_cidr_ranges=["203.0.113.5/32"] 

3937 ) 

3938 bucket.ip_filter = ip_filter 

3939 bucket.patch() 

3940 

3941 :setter: Set the IP Filter configuration for this bucket. 

3942 :getter: Gets the IP Filter configuration for this bucket. 

3943 

3944 :rtype: :class:`~google.cloud.storage.ip_filter.IPFilter` or ``NoneType`` 

3945 :returns: 

3946 An ``IPFilter`` object representing the configuration, or ``None`` 

3947 if no filter is configured. 

3948 """ 

3949 resource = self._properties.get(_IP_FILTER_PROPERTY) 

3950 if resource: 

3951 return IPFilter._from_api_resource(resource) 

3952 return None 

3953 

3954 @ip_filter.setter 

3955 def ip_filter(self, value): 

3956 if value is None: 

3957 self._patch_property(_IP_FILTER_PROPERTY, None) 

3958 elif isinstance(value, IPFilter): 

3959 self._patch_property(_IP_FILTER_PROPERTY, value._to_api_resource()) 

3960 else: 

3961 self._patch_property(_IP_FILTER_PROPERTY, value) 

3962 

3963 

3964class SoftDeletePolicy(dict): 

3965 """Map a bucket's soft delete policy. 

3966 

3967 See https://cloud.google.com/storage/docs/soft-delete 

3968 

3969 :type bucket: :class:`Bucket` 

3970 :param bucket: Bucket for which this instance is the policy. 

3971 

3972 :type retention_duration_seconds: int 

3973 :param retention_duration_seconds: 

3974 (Optional) The period of time in seconds that soft-deleted objects in the bucket 

3975 will be retained and cannot be permanently deleted. 

3976 

3977 :type effective_time: :class:`datetime.datetime` 

3978 :param effective_time: 

3979 (Optional) When the bucket's soft delete policy is effective. 

3980 This value should normally only be set by the back-end API. 

3981 """ 

3982 

3983 def __init__(self, bucket, **kw): 

3984 data = {} 

3985 retention_duration_seconds = kw.get("retention_duration_seconds") 

3986 data["retentionDurationSeconds"] = retention_duration_seconds 

3987 

3988 effective_time = kw.get("effective_time") 

3989 if effective_time is not None: 

3990 effective_time = _datetime_to_rfc3339(effective_time) 

3991 data["effectiveTime"] = effective_time 

3992 

3993 super().__init__(data) 

3994 self._bucket = bucket 

3995 

3996 @classmethod 

3997 def from_api_repr(cls, resource, bucket): 

3998 """Factory: construct instance from resource. 

3999 

4000 :type resource: dict 

4001 :param resource: mapping as returned from API call. 

4002 

4003 :type bucket: :class:`Bucket` 

4004 :params bucket: Bucket for which this instance is the policy. 

4005 

4006 :rtype: :class:`SoftDeletePolicy` 

4007 :returns: Instance created from resource. 

4008 """ 

4009 instance = cls(bucket) 

4010 instance.update(resource) 

4011 return instance 

4012 

4013 @property 

4014 def bucket(self): 

4015 """Bucket for which this instance is the policy. 

4016 

4017 :rtype: :class:`Bucket` 

4018 :returns: the instance's bucket. 

4019 """ 

4020 return self._bucket 

4021 

4022 @property 

4023 def retention_duration_seconds(self): 

4024 """Get the retention duration of the bucket's soft delete policy. 

4025 

4026 :rtype: int or ``NoneType`` 

4027 :returns: The period of time in seconds that soft-deleted objects in the bucket 

4028 will be retained and cannot be permanently deleted; Or ``None`` if the 

4029 property is not set. 

4030 """ 

4031 duration = self.get("retentionDurationSeconds") 

4032 if duration is not None: 

4033 return int(duration) 

4034 

4035 @retention_duration_seconds.setter 

4036 def retention_duration_seconds(self, value): 

4037 """Set the retention duration of the bucket's soft delete policy. 

4038 

4039 :type value: int 

4040 :param value: 

4041 The period of time in seconds that soft-deleted objects in the bucket 

4042 will be retained and cannot be permanently deleted. 

4043 """ 

4044 self["retentionDurationSeconds"] = value 

4045 self.bucket._patch_property("softDeletePolicy", self) 

4046 

4047 @property 

4048 def effective_time(self): 

4049 """Get the effective time of the bucket's soft delete policy. 

4050 

4051 :rtype: datetime.datetime or ``NoneType`` 

4052 :returns: point-in time at which the bucket's soft delte policy is 

4053 effective, or ``None`` if the property is not set. 

4054 """ 

4055 timestamp = self.get("effectiveTime") 

4056 if timestamp is not None: 

4057 return _rfc3339_nanos_to_datetime(timestamp) 

4058 

4059 

4060def _raise_if_len_differs(expected_len, **generation_match_args): 

4061 """ 

4062 Raise an error if any generation match argument 

4063 is set and its len differs from the given value. 

4064 

4065 :type expected_len: int 

4066 :param expected_len: Expected argument length in case it's set. 

4067 

4068 :type generation_match_args: dict 

4069 :param generation_match_args: Lists, which length must be checked. 

4070 

4071 :raises: :exc:`ValueError` if any argument set, but has an unexpected length. 

4072 """ 

4073 for name, value in generation_match_args.items(): 

4074 if value is not None and len(value) != expected_len: 

4075 raise ValueError(f"'{name}' length must be the same as 'blobs' length")