From 6304fa0a8e8dbbd2ca88c4810c39bec925446efb Mon Sep 17 00:00:00 2001 From: Chandra Sirimala Date: Mon, 2 Nov 2026 14:28:16 +0000 Subject: [PATCH 1/2] feat(storage): add enterprise storage class constants --- .../google/cloud/storage/constants.py | 18 ++++++++ .../tests/system/test_blob.py | 34 +++++++++++++++ .../tests/system/test_bucket.py | 42 +++++++++++++++++++ .../tests/unit/test_blob.py | 24 +++++++++++ .../tests/unit/test_bucket.py | 31 ++++++++++++++ 5 files changed, 149 insertions(+) diff --git a/packages/google-cloud-storage/google/cloud/storage/constants.py b/packages/google-cloud-storage/google/cloud/storage/constants.py index c6c1b63c413e..cecf8ddcd4b9 100644 --- a/packages/google-cloud-storage/google/cloud/storage/constants.py +++ b/packages/google-cloud-storage/google/cloud/storage/constants.py @@ -27,6 +27,18 @@ See: https://cloud.google.com/storage/docs/storage-classes """ +STANDARD_ENTERPRISE_STORAGE_CLASS = "STANDARD_ENTERPRISE" +"""Enterprise storage class for standard storage. + +See: https://cloud.google.com/storage/docs/storage-classes +""" + +STANDARD_FLEXBACKUP_ENTERPRISE_STORAGE_CLASS = "STANDARD_FLEXBACKUP_ENTERPRISE" +"""Enterprise storage class for standard flexbackup storage. + +See: https://cloud.google.com/storage/docs/storage-classes +""" + NEARLINE_STORAGE_CLASS = "NEARLINE" """Storage class for objects accessed at most once per month. @@ -45,6 +57,12 @@ See: https://cloud.google.com/storage/docs/storage-classes """ +LR_STANDARD_ENTERPRISE_STORAGE_CLASS = "LR_STANDARD_ENTERPRISE" +"""Enterprise storage class for locally redundant standard storage. + +See: https://cloud.google.com/storage/docs/storage-classes +""" + MULTI_REGIONAL_LEGACY_STORAGE_CLASS = "MULTI_REGIONAL" """Legacy storage class. diff --git a/packages/google-cloud-storage/tests/system/test_blob.py b/packages/google-cloud-storage/tests/system/test_blob.py index e3b558f5b606..b028f9db8148 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 +): + from google.cloud.storage import constants + + bucket_name = _helpers.unique_name("blob-ent-sc") + bucket = storage_client.bucket(bucket_name) + bucket.storage_class = constants.STANDARD_ENTERPRISE_STORAGE_CLASS + + 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") + info = file_data["simple"] + blob.upload_from_filename(info["path"]) + blobs_to_delete.append(blob) + assert blob.storage_class == constants.STANDARD_ENTERPRISE_STORAGE_CLASS + + blob.update_storage_class(constants.LR_STANDARD_ENTERPRISE_STORAGE_CLASS) + blob.reload() + assert blob.storage_class == constants.LR_STANDARD_ENTERPRISE_STORAGE_CLASS + + blob.update_storage_class(constants.STANDARD_ENTERPRISE_STORAGE_CLASS) + blob.reload() + assert blob.storage_class == constants.STANDARD_ENTERPRISE_STORAGE_CLASS + + 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..815737415115 100644 --- a/packages/google-cloud-storage/tests/system/test_bucket.py +++ b/packages/google-cloud-storage/tests/system/test_bucket.py @@ -49,6 +49,48 @@ 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 +): + from google.cloud.storage import constants + + enterprise_constants = ( + constants.STANDARD_ENTERPRISE_STORAGE_CLASS, + constants.LR_STANDARD_ENTERPRISE_STORAGE_CLASS, + constants.STANDARD_FLEXBACKUP_ENTERPRISE_STORAGE_CLASS, + ) + assert storage_class in enterprise_constants + + 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) + 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..6b894d38e0fa 100644 --- a/packages/google-cloud-storage/tests/unit/test_blob.py +++ b/packages/google-cloud-storage/tests/unit/test_blob.py @@ -6788,6 +6788,30 @@ def test_w_existing_qs(self): self.assertEqual(self._call_fut(BASE_URL, NV_LIST), f"{BASE_URL}&{expected}") +@pytest.mark.parametrize( + "constant_name,expected_value", + [ + ("STANDARD_ENTERPRISE_STORAGE_CLASS", "STANDARD_ENTERPRISE"), + ( + "STANDARD_FLEXBACKUP_ENTERPRISE_STORAGE_CLASS", + "STANDARD_FLEXBACKUP_ENTERPRISE", + ), + ("LR_STANDARD_ENTERPRISE_STORAGE_CLASS", "LR_STANDARD_ENTERPRISE"), + ], +) +def test_blob_storage_class_enterprise_constants(constant_name, expected_value): + from google.cloud.storage import constants + from google.cloud.storage.blob import Blob + + storage_class = getattr(constants, constant_name) + assert storage_class == expected_value + bucket = _Bucket() + blob = Blob("blob-name", bucket=bucket) + 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..b404728821d8 100644 --- a/packages/google-cloud-storage/tests/unit/test_bucket.py +++ b/packages/google-cloud-storage/tests/unit/test_bucket.py @@ -3279,6 +3279,37 @@ 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): + from google.cloud.storage.constants import STANDARD_ENTERPRISE_STORAGE_CLASS + + NAME = "name" + bucket = self._make_one(name=NAME) + bucket.storage_class = STANDARD_ENTERPRISE_STORAGE_CLASS + self.assertEqual(bucket.storage_class, STANDARD_ENTERPRISE_STORAGE_CLASS) + self.assertTrue("storageClass" in bucket._changes) + + def test_storage_class_setter_STANDARD_FLEXBACKUP_ENTERPRISE(self): + from google.cloud.storage.constants import ( + STANDARD_FLEXBACKUP_ENTERPRISE_STORAGE_CLASS, + ) + + NAME = "name" + bucket = self._make_one(name=NAME) + bucket.storage_class = STANDARD_FLEXBACKUP_ENTERPRISE_STORAGE_CLASS + self.assertEqual( + bucket.storage_class, STANDARD_FLEXBACKUP_ENTERPRISE_STORAGE_CLASS + ) + self.assertTrue("storageClass" in bucket._changes) + + def test_storage_class_setter_LR_STANDARD_ENTERPRISE(self): + from google.cloud.storage.constants import LR_STANDARD_ENTERPRISE_STORAGE_CLASS + + NAME = "name" + bucket = self._make_one(name=NAME) + bucket.storage_class = LR_STANDARD_ENTERPRISE_STORAGE_CLASS + self.assertEqual(bucket.storage_class, LR_STANDARD_ENTERPRISE_STORAGE_CLASS) + self.assertTrue("storageClass" in bucket._changes) + def test_storage_class_setter_NEARLINE(self): from google.cloud.storage.constants import NEARLINE_STORAGE_CLASS From 8f399d611b360c3592a3ae13d450507f47d4e7d9 Mon Sep 17 00:00:00 2001 From: Chandra Sirimala Date: Tue, 3 Nov 2026 05:35:30 +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 b028f9db8148..b284673ed577 100644 --- a/packages/google-cloud-storage/tests/system/test_blob.py +++ b/packages/google-cloud-storage/tests/system/test_blob.py @@ -1221,14 +1221,7 @@ def test_blob_update_storage_class_enterprise( bucket = storage_client.bucket(bucket_name) bucket.storage_class = constants.STANDARD_ENTERPRISE_STORAGE_CLASS - 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 815737415115..e9c4bb5d392b 100644 --- a/packages/google-cloud-storage/tests/system/test_bucket.py +++ b/packages/google-cloud-storage/tests/system/test_bucket.py @@ -77,14 +77,7 @@ def test_bucket_create_w_enterprise_storage_class( bucket = storage_client.bucket(bucket_name) 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)