From fb75099507c4c0798d09cc71ce66c26eae367ff3 Mon Sep 17 00:00:00 2001 From: Chandra Date: Mon, 26 Jan 2026 15:42:32 +0000 Subject: [PATCH] feat: expose finalized_time in blob.py applicable for GET_OBJECT in ZB --- google/cloud/storage/blob.py | 13 +++++++++++++ samples/snippets/storage_get_metadata.py | 1 + tests/unit/test_blob.py | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/google/cloud/storage/blob.py b/google/cloud/storage/blob.py index 746334d1c..0b022985f 100644 --- a/google/cloud/storage/blob.py +++ b/google/cloud/storage/blob.py @@ -5034,6 +5034,19 @@ def hard_delete_time(self): if hard_delete_time is not None: return _rfc3339_nanos_to_datetime(hard_delete_time) + @property + def finalized_time(self): + """If this object has been soft-deleted, returns the time at which it will be permanently deleted. + + :rtype: :class:`datetime.datetime` or ``NoneType`` + :returns: + (readonly) The time that the object will be permanently deleted. + Note this property is only set for soft-deleted objects. + """ + finalize_time = self._properties.get("finalizedTime", None) + if finalize_time is not None: + return _rfc3339_nanos_to_datetime(finalize_time) + def _get_host_name(connection): """Returns the host name from the given connection. diff --git a/samples/snippets/storage_get_metadata.py b/samples/snippets/storage_get_metadata.py index 7216efdb4..1e332b445 100644 --- a/samples/snippets/storage_get_metadata.py +++ b/samples/snippets/storage_get_metadata.py @@ -34,6 +34,7 @@ def blob_metadata(bucket_name, blob_name): blob = bucket.get_blob(blob_name) print(f"Blob: {blob.name}") + print(f"Blob finalization: {blob.finalized_time}") print(f"Bucket: {blob.bucket.name}") print(f"Storage class: {blob.storage_class}") print(f"ID: {blob.id}") diff --git a/tests/unit/test_blob.py b/tests/unit/test_blob.py index a8abb1571..2359de501 100644 --- a/tests/unit/test_blob.py +++ b/tests/unit/test_blob.py @@ -228,6 +228,29 @@ def test__set_properties_w_kms_key_name(self): ) self._set_properties_helper(kms_key_name=kms_resource) + def test_finalized_time_property_is_none(self): + BLOB_NAME = "blob-name" + bucket = _Bucket() + blob = self._make_one(BLOB_NAME, bucket=bucket) + self.assertIsNone(blob.finalized_time) + + def test_finalized_time_property_is_not_none(self): + from google.cloud.storage import blob as blob_module + + BLOB_NAME = "blob-name" + bucket = _Bucket() + blob = self._make_one(BLOB_NAME, bucket=bucket) + + timestamp = "2024-07-29T12:34:56.123456Z" + blob._properties["finalizedTime"] = timestamp + + mock_datetime = mock.Mock() + with mock.patch.object( + blob_module, "_rfc3339_nanos_to_datetime", return_value=mock_datetime + ) as mocked: + self.assertEqual(blob.finalized_time, mock_datetime) + mocked.assert_called_once_with(timestamp) + def test_chunk_size_ctor(self): from google.cloud.storage.blob import Blob