From c38c1d6374b44f3361bd91b236de53e7c44cf12b Mon Sep 17 00:00:00 2001 From: Chandra Sirimala Date: Mon, 2 Nov 2026 14:28:11 +0000 Subject: [PATCH 1/2] feat(storage): add enterprise storage classes to Bucket and Blob STORAGE_CLASSES tuples --- .../google/cloud/storage/blob.py | 3 ++ .../google/cloud/storage/bucket.py | 3 ++ .../tests/system/test_blob.py | 34 +++++++++++++++++++ .../tests/system/test_bucket.py | 34 +++++++++++++++++++ .../tests/unit/test_blob.py | 19 +++++++++++ .../tests/unit/test_bucket.py | 24 +++++++++++++ 6 files changed, 117 insertions(+) diff --git a/packages/google-cloud-storage/google/cloud/storage/blob.py b/packages/google-cloud-storage/google/cloud/storage/blob.py index 87493a30dfc0..4742731db393 100644 --- a/packages/google-cloud-storage/google/cloud/storage/blob.py +++ b/packages/google-cloud-storage/google/cloud/storage/blob.py @@ -191,9 +191,12 @@ class Blob(_PropertyMixin): STORAGE_CLASSES = ( STANDARD_STORAGE_CLASS, + "STANDARD_ENTERPRISE", + "STANDARD_FLEXBACKUP_ENTERPRISE", NEARLINE_STORAGE_CLASS, COLDLINE_STORAGE_CLASS, ARCHIVE_STORAGE_CLASS, + "LR_STANDARD_ENTERPRISE", MULTI_REGIONAL_LEGACY_STORAGE_CLASS, REGIONAL_LEGACY_STORAGE_CLASS, ) diff --git a/packages/google-cloud-storage/google/cloud/storage/bucket.py b/packages/google-cloud-storage/google/cloud/storage/bucket.py index 7954e70e08f9..9de8f6fbadbf 100644 --- a/packages/google-cloud-storage/google/cloud/storage/bucket.py +++ b/packages/google-cloud-storage/google/cloud/storage/bucket.py @@ -650,9 +650,12 @@ class Bucket(_PropertyMixin): STORAGE_CLASSES = ( STANDARD_STORAGE_CLASS, + "STANDARD_ENTERPRISE", + "STANDARD_FLEXBACKUP_ENTERPRISE", NEARLINE_STORAGE_CLASS, COLDLINE_STORAGE_CLASS, ARCHIVE_STORAGE_CLASS, + "LR_STANDARD_ENTERPRISE", MULTI_REGIONAL_LEGACY_STORAGE_CLASS, # legacy REGIONAL_LEGACY_STORAGE_CLASS, # legacy DURABLE_REDUCED_AVAILABILITY_LEGACY_STORAGE_CLASS, # legacy diff --git a/packages/google-cloud-storage/tests/system/test_blob.py b/packages/google-cloud-storage/tests/system/test_blob.py index e3b558f5b606..7160aafb3853 100644 --- a/packages/google-cloud-storage/tests/system/test_blob.py +++ b/packages/google-cloud-storage/tests/system/test_blob.py @@ -1212,6 +1212,40 @@ def test_blob_update_storage_class_large_file( assert blob.storage_class == constants.COLDLINE_STORAGE_CLASS +def test_blob_update_storage_class_enterprise( + storage_client, buckets_to_delete, blobs_to_delete, file_data +): + bucket_name = _helpers.unique_name("blob-ent-sc") + bucket = storage_client.bucket(bucket_name) + bucket.storage_class = "STANDARD_ENTERPRISE" + + try: + _helpers.retry_429_503(bucket.create)(location="us-central1") + except exceptions.BadRequest as exc: + if "is not allowed for project" in str( + exc + ) or "may not create storageClass" in str(exc): + pytest.skip(f"Project not allowlisted for enterprise storage class: {exc}") + raise + buckets_to_delete.append(bucket) + + blob = bucket.blob("EnterpriseSmallFile") + assert "STANDARD_ENTERPRISE" in blob.STORAGE_CLASSES + assert "LR_STANDARD_ENTERPRISE" in blob.STORAGE_CLASSES + info = file_data["simple"] + blob.upload_from_filename(info["path"]) + blobs_to_delete.append(blob) + assert blob.storage_class == "STANDARD_ENTERPRISE" + + blob.update_storage_class("LR_STANDARD_ENTERPRISE") + blob.reload() + assert blob.storage_class == "LR_STANDARD_ENTERPRISE" + + blob.update_storage_class("STANDARD_ENTERPRISE") + blob.reload() + assert blob.storage_class == "STANDARD_ENTERPRISE" + + def test_object_retention_lock(storage_client, buckets_to_delete, blobs_to_delete): from google.cloud.storage._helpers import _NOW, _UTC diff --git a/packages/google-cloud-storage/tests/system/test_bucket.py b/packages/google-cloud-storage/tests/system/test_bucket.py index ae194fe46793..1c30d4e34738 100644 --- a/packages/google-cloud-storage/tests/system/test_bucket.py +++ b/packages/google-cloud-storage/tests/system/test_bucket.py @@ -49,6 +49,40 @@ def test_bucket_create_w_alt_storage_class(storage_client, buckets_to_delete): assert created.storage_class == constants.ARCHIVE_STORAGE_CLASS +@pytest.mark.parametrize( + "storage_class,suffix,location", + [ + ("STANDARD_ENTERPRISE", "std-ent", "us-central1"), + ("LR_STANDARD_ENTERPRISE", "lr-std-ent", "us-central1"), + ("STANDARD_FLEXBACKUP_ENTERPRISE", "fb-ent", "us"), + ], +) +def test_bucket_create_w_enterprise_storage_class( + storage_client, buckets_to_delete, storage_class, suffix, location +): + bucket_name = _helpers.unique_name(f"bucket-w-{suffix}") + + with pytest.raises(exceptions.NotFound): + storage_client.get_bucket(bucket_name) + + bucket = storage_client.bucket(bucket_name) + assert storage_class in bucket.STORAGE_CLASSES + bucket.storage_class = storage_class + + try: + _helpers.retry_429_503(bucket.create)(location=location) + except exceptions.BadRequest as exc: + if "is not allowed for project" in str( + exc + ) or "may not create storageClass" in str(exc): + pytest.skip(f"Project not allowlisted for enterprise storage class: {exc}") + raise + buckets_to_delete.append(bucket) + + created = storage_client.get_bucket(bucket_name) + assert created.storage_class == storage_class + + def test_bucket_lifecycle_rules(storage_client, buckets_to_delete): from google.cloud.storage import constants from google.cloud.storage.bucket import ( diff --git a/packages/google-cloud-storage/tests/unit/test_blob.py b/packages/google-cloud-storage/tests/unit/test_blob.py index c5609e3dd5c6..b4fa0e1808c0 100644 --- a/packages/google-cloud-storage/tests/unit/test_blob.py +++ b/packages/google-cloud-storage/tests/unit/test_blob.py @@ -6788,6 +6788,25 @@ def test_w_existing_qs(self): self.assertEqual(self._call_fut(BASE_URL, NV_LIST), f"{BASE_URL}&{expected}") +@pytest.mark.parametrize( + "storage_class", + [ + "STANDARD_ENTERPRISE", + "STANDARD_FLEXBACKUP_ENTERPRISE", + "LR_STANDARD_ENTERPRISE", + ], +) +def test_blob_storage_class_enterprise_tuples(storage_class): + from google.cloud.storage.blob import Blob + + bucket = _Bucket() + blob = Blob("blob-name", bucket=bucket) + assert storage_class in blob.STORAGE_CLASSES + blob.storage_class = storage_class + assert blob.storage_class == storage_class + assert blob._properties == {"storageClass": storage_class} + + class _Connection(object): API_BASE_URL = "http://example.com" USER_AGENT = "testing 1.2.3" diff --git a/packages/google-cloud-storage/tests/unit/test_bucket.py b/packages/google-cloud-storage/tests/unit/test_bucket.py index 19b3456b816e..7546d2e52e09 100644 --- a/packages/google-cloud-storage/tests/unit/test_bucket.py +++ b/packages/google-cloud-storage/tests/unit/test_bucket.py @@ -3279,6 +3279,30 @@ def test_storage_class_setter_STANDARD(self): self.assertEqual(bucket.storage_class, STANDARD_STORAGE_CLASS) self.assertTrue("storageClass" in bucket._changes) + def test_storage_class_setter_STANDARD_ENTERPRISE(self): + NAME = "name" + bucket = self._make_one(name=NAME) + self.assertIn("STANDARD_ENTERPRISE", bucket.STORAGE_CLASSES) + bucket.storage_class = "STANDARD_ENTERPRISE" + self.assertEqual(bucket.storage_class, "STANDARD_ENTERPRISE") + self.assertTrue("storageClass" in bucket._changes) + + def test_storage_class_setter_STANDARD_FLEXBACKUP_ENTERPRISE(self): + NAME = "name" + bucket = self._make_one(name=NAME) + self.assertIn("STANDARD_FLEXBACKUP_ENTERPRISE", bucket.STORAGE_CLASSES) + bucket.storage_class = "STANDARD_FLEXBACKUP_ENTERPRISE" + self.assertEqual(bucket.storage_class, "STANDARD_FLEXBACKUP_ENTERPRISE") + self.assertTrue("storageClass" in bucket._changes) + + def test_storage_class_setter_LR_STANDARD_ENTERPRISE(self): + NAME = "name" + bucket = self._make_one(name=NAME) + self.assertIn("LR_STANDARD_ENTERPRISE", bucket.STORAGE_CLASSES) + bucket.storage_class = "LR_STANDARD_ENTERPRISE" + self.assertEqual(bucket.storage_class, "LR_STANDARD_ENTERPRISE") + self.assertTrue("storageClass" in bucket._changes) + def test_storage_class_setter_NEARLINE(self): from google.cloud.storage.constants import NEARLINE_STORAGE_CLASS From c8828a074d859eda6e6722d7b273771862116c7e Mon Sep 17 00:00:00 2001 From: Chandra Sirimala Date: Tue, 3 Nov 2026 05:35:25 +0000 Subject: [PATCH 2/2] test(storage): remove pytest.skip from enterprise storage class system tests --- packages/google-cloud-storage/tests/system/test_blob.py | 9 +-------- .../google-cloud-storage/tests/system/test_bucket.py | 9 +-------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/packages/google-cloud-storage/tests/system/test_blob.py b/packages/google-cloud-storage/tests/system/test_blob.py index 7160aafb3853..4be7b54b138e 100644 --- a/packages/google-cloud-storage/tests/system/test_blob.py +++ b/packages/google-cloud-storage/tests/system/test_blob.py @@ -1219,14 +1219,7 @@ def test_blob_update_storage_class_enterprise( bucket = storage_client.bucket(bucket_name) bucket.storage_class = "STANDARD_ENTERPRISE" - try: - _helpers.retry_429_503(bucket.create)(location="us-central1") - except exceptions.BadRequest as exc: - if "is not allowed for project" in str( - exc - ) or "may not create storageClass" in str(exc): - pytest.skip(f"Project not allowlisted for enterprise storage class: {exc}") - raise + _helpers.retry_429_503(bucket.create)(location="us-central1") buckets_to_delete.append(bucket) blob = bucket.blob("EnterpriseSmallFile") diff --git a/packages/google-cloud-storage/tests/system/test_bucket.py b/packages/google-cloud-storage/tests/system/test_bucket.py index 1c30d4e34738..e1a04dd3476d 100644 --- a/packages/google-cloud-storage/tests/system/test_bucket.py +++ b/packages/google-cloud-storage/tests/system/test_bucket.py @@ -69,14 +69,7 @@ def test_bucket_create_w_enterprise_storage_class( assert storage_class in bucket.STORAGE_CLASSES bucket.storage_class = storage_class - try: - _helpers.retry_429_503(bucket.create)(location=location) - except exceptions.BadRequest as exc: - if "is not allowed for project" in str( - exc - ) or "may not create storageClass" in str(exc): - pytest.skip(f"Project not allowlisted for enterprise storage class: {exc}") - raise + _helpers.retry_429_503(bucket.create)(location=location) buckets_to_delete.append(bucket) created = storage_client.get_bucket(bucket_name)