From 04077ab9dcda9ce6dfc7d6717de9c22a3f66ade8 Mon Sep 17 00:00:00 2001 From: Cathy Ouyang Date: Wed, 20 Apr 2022 11:53:14 -0700 Subject: [PATCH 1/2] feat: support OLM Prefix/Suffix --- google/cloud/storage/bucket.py | 27 ++++++++++++++++++++++++++- tests/system/test_bucket.py | 18 ++++++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/google/cloud/storage/bucket.py b/google/cloud/storage/bucket.py index be99ad141..7254a2c8d 100644 --- a/google/cloud/storage/bucket.py +++ b/google/cloud/storage/bucket.py @@ -163,11 +163,19 @@ class LifecycleRuleConditions(dict): rule action to versioned items with at least one newer version. + :type matches_prefix: list(str) + :param matches_prefix: (Optional) Apply rule action to items which + any prefix matches the beginning of the item name. + :type matches_storage_class: list(str), one or more of :attr:`Bucket.STORAGE_CLASSES`. - :param matches_storage_class: (Optional) Apply rule action to items which + :param matches_storage_class: (Optional) Apply rule action to items whose storage class matches this value. + :type matches_suffix: list(str) + :param matches_suffix: (Optional) Apply rule action to items which + any suffix matches the end of the item name. + :type number_of_newer_versions: int :param number_of_newer_versions: (Optional) Apply rule action to versioned items having N newer versions. @@ -211,6 +219,8 @@ def __init__( custom_time_before=None, days_since_noncurrent_time=None, noncurrent_time_before=None, + matches_prefix=None, + matches_suffix=None, _factory=False, ): conditions = {} @@ -245,6 +255,11 @@ def __init__( if noncurrent_time_before is not None: conditions["noncurrentTimeBefore"] = noncurrent_time_before.isoformat() + if matches_prefix is not None: + conditions["matchesPrefix"] = matches_prefix + + if matches_suffix is not None: + conditions["matchesSuffix"] = matches_suffix super(LifecycleRuleConditions, self).__init__(conditions) @classmethod @@ -278,11 +293,21 @@ def is_live(self): """Conditon's 'is_live' value.""" return self.get("isLive") + @property + def matches_prefix(self): + """Conditon's 'matches_prefix' value.""" + return self.get("matchesPrefix") + @property def matches_storage_class(self): """Conditon's 'matches_storage_class' value.""" return self.get("matchesStorageClass") + @property + def matches_suffix(self): + """Conditon's 'matches_suffix' value.""" + return self.get("matchesSuffix") + @property def number_of_newer_versions(self): """Conditon's 'number_of_newer_versions' value.""" diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index de1a04aa9..5e814d4b9 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -47,6 +47,8 @@ def test_bucket_lifecycle_rules(storage_client, buckets_to_delete): bucket_name = _helpers.unique_name("w-lifcycle-rules") custom_time_before = datetime.date(2018, 8, 1) noncurrent_before = datetime.date(2018, 8, 1) + matches_prefix = ["storage-sys-test", "gcs-sys-test"] + matches_suffix = ["suffix-test"] with pytest.raises(exceptions.NotFound): storage_client.get_bucket(bucket_name) @@ -59,6 +61,8 @@ def test_bucket_lifecycle_rules(storage_client, buckets_to_delete): custom_time_before=custom_time_before, days_since_noncurrent_time=2, noncurrent_time_before=noncurrent_before, + matches_prefix=matches_prefix, + matches_suffix=matches_suffix, ) bucket.add_lifecycle_set_storage_class_rule( constants.COLDLINE_STORAGE_CLASS, @@ -77,6 +81,8 @@ def test_bucket_lifecycle_rules(storage_client, buckets_to_delete): custom_time_before=custom_time_before, days_since_noncurrent_time=2, noncurrent_time_before=noncurrent_before, + matches_prefix=matches_prefix, + matches_suffix=matches_suffix, ), LifecycleRuleSetStorageClass( constants.COLDLINE_STORAGE_CLASS, @@ -95,9 +101,17 @@ def test_bucket_lifecycle_rules(storage_client, buckets_to_delete): assert list(bucket.lifecycle_rules) == expected_rules # Test modifying lifecycle rules - expected_rules[0] = LifecycleRuleDelete(age=30) + expected_rules[0] = LifecycleRuleDelete( + age=30, + matches_prefix="new-prefix", + matches_suffix="new-suffix", + ) rules = list(bucket.lifecycle_rules) - rules[0]["condition"] = {"age": 30} + rules[0]["condition"] = { + "age": 30, + "matchesPrefix": "new-prefix", + "matchesSuffix": "new-suffix", + } bucket.lifecycle_rules = rules bucket.patch() From d9a4d23378dbdd06bf865e0d33be63b4966c7bc0 Mon Sep 17 00:00:00 2001 From: Cathy Ouyang Date: Wed, 20 Apr 2022 12:16:19 -0700 Subject: [PATCH 2/2] update tests --- google/cloud/storage/bucket.py | 7 ++++--- tests/system/test_bucket.py | 8 ++++---- tests/unit/test_bucket.py | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/google/cloud/storage/bucket.py b/google/cloud/storage/bucket.py index 7254a2c8d..8c9745487 100644 --- a/google/cloud/storage/bucket.py +++ b/google/cloud/storage/bucket.py @@ -246,9 +246,6 @@ def __init__( if custom_time_before is not None: conditions["customTimeBefore"] = custom_time_before.isoformat() - if not _factory and not conditions: - raise ValueError("Supply at least one condition") - if days_since_noncurrent_time is not None: conditions["daysSinceNoncurrentTime"] = days_since_noncurrent_time @@ -260,6 +257,10 @@ def __init__( if matches_suffix is not None: conditions["matchesSuffix"] = matches_suffix + + if not _factory and not conditions: + raise ValueError("Supply at least one condition") + super(LifecycleRuleConditions, self).__init__(conditions) @classmethod diff --git a/tests/system/test_bucket.py b/tests/system/test_bucket.py index 5e814d4b9..a0cccdde1 100644 --- a/tests/system/test_bucket.py +++ b/tests/system/test_bucket.py @@ -103,14 +103,14 @@ def test_bucket_lifecycle_rules(storage_client, buckets_to_delete): # Test modifying lifecycle rules expected_rules[0] = LifecycleRuleDelete( age=30, - matches_prefix="new-prefix", - matches_suffix="new-suffix", + matches_prefix=["new-prefix"], + matches_suffix=["new-suffix"], ) rules = list(bucket.lifecycle_rules) rules[0]["condition"] = { "age": 30, - "matchesPrefix": "new-prefix", - "matchesSuffix": "new-suffix", + "matchesPrefix": ["new-prefix"], + "matchesSuffix": ["new-suffix"], } bucket.lifecycle_rules = rules bucket.patch() diff --git a/tests/unit/test_bucket.py b/tests/unit/test_bucket.py index eb402de9e..d3c3101cc 100644 --- a/tests/unit/test_bucket.py +++ b/tests/unit/test_bucket.py @@ -230,6 +230,28 @@ def test_ctor_w_noncurrent_time_before(self): self.assertEqual(conditions.number_of_newer_versions, 3) self.assertEqual(conditions.noncurrent_time_before, noncurrent_before) + def test_ctor_w_matches_prefix(self): + conditions = self._make_one(matches_prefix=["test-prefix"]) + expected = {"matchesPrefix": ["test-prefix"]} + self.assertEqual(dict(conditions), expected) + self.assertIsNone(conditions.age) + self.assertIsNone(conditions.created_before) + self.assertIsNone(conditions.is_live) + self.assertIsNone(conditions.matches_storage_class) + self.assertIsNone(conditions.matches_suffix) + self.assertEqual(conditions.matches_prefix, ["test-prefix"]) + + def test_ctor_w_matches_suffix(self): + conditions = self._make_one(matches_suffix=["test-suffix"]) + expected = {"matchesSuffix": ["test-suffix"]} + self.assertEqual(dict(conditions), expected) + self.assertIsNone(conditions.age) + self.assertIsNone(conditions.created_before) + self.assertIsNone(conditions.is_live) + self.assertIsNone(conditions.matches_storage_class) + self.assertIsNone(conditions.matches_prefix) + self.assertEqual(conditions.matches_suffix, ["test-suffix"]) + def test_from_api_repr(self): import datetime