Skip to content

Commit 6a1866e

Browse files
committed
Add bucket properties to support retention policy feature. (#447)
Toward #445.
1 parent f6048da commit 6a1866e

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed

storage/google/cloud/storage/bucket.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,21 @@ def cors(self, entries):
791791
"""
792792
self._patch_property('cors', entries)
793793

794+
default_event_based_hold = _scalar_property('defaultEventBasedHold')
795+
"""Are uploaded objects automatically placed under an even-based hold?
796+
797+
If True, uploaded objects will be placed under an event-based hold to
798+
be released at a future time. When released an object will then begin
799+
the retention period determined by the policy retention period for the
800+
object bucket.
801+
802+
See https://cloud.google.com/storage/docs/json_api/v1/buckets
803+
804+
If the property is not set locally, returns ``None``.
805+
806+
:rtype: bool or ``NoneType``
807+
"""
808+
794809
@property
795810
def default_kms_key_name(self):
796811
"""Retrieve / set default KMS encryption key for objects in the bucket.
@@ -1019,6 +1034,64 @@ def project_number(self):
10191034
if project_number is not None:
10201035
return int(project_number)
10211036

1037+
@property
1038+
def retention_policy_effective_time(self):
1039+
"""Retrieve the effective time of the bucket's retention policy.
1040+
1041+
:rtype: datetime.datetime or ``NoneType``
1042+
:returns: point-in time at which the bucket's retention policy is
1043+
effective, or ``None`` if the property is not
1044+
set locally.
1045+
"""
1046+
policy = self._properties.get('retentionPolicy')
1047+
if policy is not None:
1048+
timestamp = policy.get('effectiveTime')
1049+
if timestamp is not None:
1050+
return _rfc3339_to_datetime(timestamp)
1051+
1052+
@property
1053+
def retention_policy_locked(self):
1054+
"""Retrieve whthere the bucket's retention policy is locked.
1055+
1056+
:rtype: bool
1057+
:returns: True if the bucket's policy is locked, or else False
1058+
if the policy is not locked, or the property is not
1059+
set locally.
1060+
"""
1061+
policy = self._properties.get('retentionPolicy')
1062+
if policy is not None:
1063+
return policy.get('isLocked')
1064+
1065+
@property
1066+
def retention_period(self):
1067+
"""Retrieve or set the retention period for items in the bucket.
1068+
1069+
:rtype: int or ``NoneType``
1070+
:returns: number of seconds to retain items after upload or release
1071+
from event-based lock, or ``None`` if the property is not
1072+
set locally.
1073+
"""
1074+
policy = self._properties.get('retentionPolicy')
1075+
if policy is not None:
1076+
period = policy.get('retentionPeriod')
1077+
if period is not None:
1078+
return int(period)
1079+
1080+
@retention_period.setter
1081+
def retention_period(self, value):
1082+
"""Set the retention period for items in the bucket.
1083+
1084+
:type value: int
1085+
:param value:
1086+
number of seconds to retain items after upload or release from
1087+
event-based lock.
1088+
1089+
:raises ValueError: if the bucket's retention policy is locked.
1090+
"""
1091+
policy = self._properties.setdefault('retentionPolicy', {})
1092+
policy['retentionPeriod'] = str(value)
1093+
self._patch_property('retentionPolicy', policy)
1094+
10221095
@property
10231096
def self_link(self):
10241097
"""Retrieve the URI for the bucket.

storage/tests/unit/test_bucket.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,92 @@ def test_project_number_string_val(self):
11281128
bucket = self._make_one(properties=properties)
11291129
self.assertEqual(bucket.project_number, PROJECT_NUMBER)
11301130

1131+
def test_retention_policy_effective_time_policy_missing(self):
1132+
bucket = self._make_one()
1133+
self.assertIsNone(bucket.retention_policy_effective_time)
1134+
1135+
def test_retention_policy_effective_time_et_missing(self):
1136+
properties = {
1137+
'retentionPolicy': {
1138+
},
1139+
}
1140+
bucket = self._make_one(properties=properties)
1141+
1142+
self.assertIsNone(bucket.retention_policy_effective_time)
1143+
1144+
def test_retention_policy_effective_time(self):
1145+
import datetime
1146+
from google.cloud._helpers import _datetime_to_rfc3339
1147+
from google.cloud._helpers import UTC
1148+
1149+
effective_time = datetime.datetime.utcnow().replace(tzinfo=UTC)
1150+
properties = {
1151+
'retentionPolicy': {
1152+
'effectiveTime': _datetime_to_rfc3339(effective_time),
1153+
},
1154+
}
1155+
bucket = self._make_one(properties=properties)
1156+
1157+
self.assertEqual(
1158+
bucket.retention_policy_effective_time, effective_time)
1159+
1160+
def test_retention_policy_locked_missing(self):
1161+
bucket = self._make_one()
1162+
self.assertFalse(bucket.retention_policy_locked)
1163+
1164+
def test_retention_policy_locked_false(self):
1165+
properties = {
1166+
'retentionPolicy': {
1167+
'isLocked': False,
1168+
},
1169+
}
1170+
bucket = self._make_one(properties=properties)
1171+
self.assertFalse(bucket.retention_policy_locked)
1172+
1173+
def test_retention_policy_locked_true(self):
1174+
properties = {
1175+
'retentionPolicy': {
1176+
'isLocked': True,
1177+
},
1178+
}
1179+
bucket = self._make_one(properties=properties)
1180+
self.assertTrue(bucket.retention_policy_locked)
1181+
1182+
def test_retention_period_getter_policymissing(self):
1183+
bucket = self._make_one()
1184+
1185+
self.assertIsNone(bucket.retention_period)
1186+
1187+
def test_retention_period_getter_pr_missing(self):
1188+
properties = {
1189+
'retentionPolicy': {
1190+
},
1191+
}
1192+
bucket = self._make_one(properties=properties)
1193+
1194+
self.assertIsNone(bucket.retention_period)
1195+
1196+
def test_retention_period_getter(self):
1197+
period = 86400 * 100 # 100 days
1198+
properties = {
1199+
'retentionPolicy': {
1200+
'retentionPeriod': str(period),
1201+
},
1202+
}
1203+
bucket = self._make_one(properties=properties)
1204+
1205+
self.assertEqual(bucket.retention_period, period)
1206+
1207+
def test_retention_period_setter(self):
1208+
period = 86400 * 100 # 100 days
1209+
bucket = self._make_one()
1210+
1211+
bucket.retention_period = period
1212+
1213+
self.assertEqual(
1214+
bucket._properties['retentionPolicy']['retentionPeriod'],
1215+
str(period))
1216+
11311217
def test_self_link(self):
11321218
SELF_LINK = 'http://example.com/self/'
11331219
properties = {'selfLink': SELF_LINK}

0 commit comments

Comments
 (0)