Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for soft delete #1229

Merged
merged 7 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Prev Previous commit
update docstrings; address comments
  • Loading branch information
cojenco committed Mar 18, 2024
commit 28cd89ecc8adf1d0bae89bdfc2c82009038a6993
13 changes: 10 additions & 3 deletions google/cloud/storage/_helpers.py
Expand Up @@ -225,7 +225,7 @@ def reload(
if_metageneration_not_match=None,
timeout=_DEFAULT_TIMEOUT,
retry=DEFAULT_RETRY,
**kwargs,
soft_deleted=None,
):
"""Reload properties from Cloud Storage.

Expand Down Expand Up @@ -271,6 +271,13 @@ def reload(
:type retry: google.api_core.retry.Retry or google.cloud.storage.retry.ConditionalRetryPolicy
:param retry:
(Optional) How to retry the RPC. See: :ref:`configuring_retries`

:type soft_deleted: bool
:param soft_deleted:
(Optional) If True, looks for a soft-deleted object. Will only return
the object metadata if the object exists and is in a soft-deleted state.
:attr:`generation` is required to be set on the blob if ``soft_deleted`` is set to True.
See: https://cloud.google.com/storage/docs/soft-delete
"""
client = self._require_client(client)
query_params = self._query_params
Expand All @@ -284,8 +291,8 @@ def reload(
if_metageneration_match=if_metageneration_match,
if_metageneration_not_match=if_metageneration_not_match,
)
if kwargs.get("soft_deleted") is not None:
query_params["softDeleted"] = kwargs["soft_deleted"]
if soft_deleted is not None:
query_params["softDeleted"] = soft_deleted
headers = self._encryption_headers()
_add_etag_match_headers(
headers, if_etag_match=if_etag_match, if_etag_not_match=if_etag_not_match
Expand Down
4 changes: 3 additions & 1 deletion google/cloud/storage/blob.py
Expand Up @@ -697,8 +697,10 @@ def exists(

:type soft_deleted: bool
:param soft_deleted:
(Optional) If true, determines whether or not this soft-deleted object exists.
(Optional) If True, looks for a soft-deleted object. Will only return True
if the object exists and is in a soft-deleted state.
:attr:`generation` is required to be set on the blob if ``soft_deleted`` is set to True.
See: https://cloud.google.com/storage/docs/soft-delete

:rtype: bool
:returns: True if the blob exists in Cloud Storage.
Expand Down
16 changes: 13 additions & 3 deletions google/cloud/storage/bucket.py
Expand Up @@ -1251,8 +1251,10 @@ def get_blob(

:type soft_deleted: bool
:param soft_deleted:
(Optional) If true, returns the soft-deleted object.
(Optional) If True, looks for a soft-deleted object. Will only return
the object metadata if the object exists and is in a soft-deleted state.
Object ``generation`` is required if ``soft_deleted`` is set to True.
See: https://cloud.google.com/storage/docs/soft-delete

:param kwargs: Keyword arguments to pass to the
:class:`~google.cloud.storage.blob.Blob` constructor.
Expand Down Expand Up @@ -1388,8 +1390,10 @@ def list_blobs(

:type soft_deleted: bool
:param soft_deleted:
(Optional) If true, only soft-deleted object versions will be listed as distinct results in order
of generation number. Note ``soft_deleted`` and ``versions`` cannot be set to True simultaneously.
(Optional) If true, only soft-deleted objects will be listed as distinct results in order of increasing
generation number. This parameter can only be used successfully if the bucket has a soft delete policy.
Note ``soft_deleted`` and ``versions`` cannot be set to True simultaneously. See:
https://cloud.google.com/storage/docs/soft-delete

:rtype: :class:`~google.api_core.page_iterator.Iterator`
:returns: Iterator of all :class:`~google.cloud.storage.blob.Blob`
Expand Down Expand Up @@ -2092,6 +2096,8 @@ def restore_blob(

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

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

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

Expand Down Expand Up @@ -2347,6 +2353,8 @@ def iam_configuration(self):
def soft_delete_policy(self):
"""Retrieve the soft delete policy for this bucket.

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

:rtype: :class:`SoftDeletePolicy`
:returns: an instance for managing the bucket's soft delete policy.
"""
Expand Down Expand Up @@ -3561,6 +3569,8 @@ def generate_signed_url(
class SoftDeletePolicy(dict):
"""Map a bucket's soft delete policy.

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

:type bucket: :class:`Bucket`
:param bucket: Bucket for which this instance is the policy.

Expand Down
7 changes: 4 additions & 3 deletions google/cloud/storage/client.py
Expand Up @@ -1284,9 +1284,10 @@ def list_blobs(
https://cloud.google.com/storage/docs/json_api/v1/objects/list#list-object-glob

soft_deleted (bool):
(Optional) If true, only soft-deleted object versions will be listed as distinct results in order
of generation number. Note ``soft_deleted`` and ``versions`` cannot be set to True simultaneously.
https://cloud.google.com/storage/docs/json_api/v1/objects/list#list-object-glob
(Optional) If true, only soft-deleted objects will be listed as distinct results in order of increasing
generation number. This parameter can only be used successfully if the bucket has a soft delete policy.
Note ``soft_deleted`` and ``versions`` cannot be set to True simultaneously. See:
https://cloud.google.com/storage/docs/soft-delete

Returns:
Iterator of all :class:`~google.cloud.storage.blob.Blob`
Expand Down
1 change: 1 addition & 0 deletions tests/system/test_bucket.py
Expand Up @@ -1187,6 +1187,7 @@ def test_soft_delete_policy(

# Restore the soft-deleted object.
restored_blob = bucket.restore_blob(blob_name, generation=gen)
assert restored_blob.exists() is True
assert restored_blob.generation != gen

# Patch the soft delete policy on an existing bucket.
Expand Down