Skip to content

Commit bf18051

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

2 files changed

Lines changed: 159 additions & 0 deletions

File tree

storage/google/cloud/storage/bucket.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,21 @@ def cors(self, entries):
801801
"""
802802
self._patch_property('cors', entries)
803803

804+
default_event_based_hold = _scalar_property('defaultEventBasedHold')
805+
"""Are uploaded objects automatically placed under an even-based hold?
806+
807+
If True, uploaded objects will be placed under an event-based hold to
808+
be released at a future time. When released an object will then begin
809+
the retention period determined by the policy retention period for the
810+
object bucket.
811+
812+
See https://cloud.google.com/storage/docs/json_api/v1/buckets
813+
814+
If the property is not set locally, returns ``None``.
815+
816+
:rtype: bool or ``NoneType``
817+
"""
818+
804819
@property
805820
def default_kms_key_name(self):
806821
"""Retrieve / set default KMS encryption key for objects in the bucket.
@@ -1055,6 +1070,64 @@ def project_number(self):
10551070
if project_number is not None:
10561071
return int(project_number)
10571072

1073+
@property
1074+
def retention_policy_effective_time(self):
1075+
"""Retrieve the effective time of the bucket's retention policy.
1076+
1077+
:rtype: datetime.datetime or ``NoneType``
1078+
:returns: point-in time at which the bucket's retention policy is
1079+
effective, or ``None`` if the property is not
1080+
set locally.
1081+
"""
1082+
policy = self._properties.get('retentionPolicy')
1083+
if policy is not None:
1084+
timestamp = policy.get('effectiveTime')
1085+
if timestamp is not None:
1086+
return _rfc3339_to_datetime(timestamp)
1087+
1088+
@property
1089+
def retention_policy_locked(self):
1090+
"""Retrieve whthere the bucket's retention policy is locked.
1091+
1092+
:rtype: bool
1093+
:returns: True if the bucket's policy is locked, or else False
1094+
if the policy is not locked, or the property is not
1095+
set locally.
1096+
"""
1097+
policy = self._properties.get('retentionPolicy')
1098+
if policy is not None:
1099+
return policy.get('isLocked')
1100+
1101+
@property
1102+
def retention_period(self):
1103+
"""Retrieve or set the retention period for items in the bucket.
1104+
1105+
:rtype: int or ``NoneType``
1106+
:returns: number of seconds to retain items after upload or release
1107+
from event-based lock, or ``None`` if the property is not
1108+
set locally.
1109+
"""
1110+
policy = self._properties.get('retentionPolicy')
1111+
if policy is not None:
1112+
period = policy.get('retentionPeriod')
1113+
if period is not None:
1114+
return int(period)
1115+
1116+
@retention_period.setter
1117+
def retention_period(self, value):
1118+
"""Set the retention period for items in the bucket.
1119+
1120+
:type value: int
1121+
:param value:
1122+
number of seconds to retain items after upload or release from
1123+
event-based lock.
1124+
1125+
:raises ValueError: if the bucket's retention policy is locked.
1126+
"""
1127+
policy = self._properties.setdefault('retentionPolicy', {})
1128+
policy['retentionPeriod'] = str(value)
1129+
self._patch_property('retentionPolicy', policy)
1130+
10581131
@property
10591132
def self_link(self):
10601133
"""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
@@ -1147,6 +1147,92 @@ def test_project_number_string_val(self):
11471147
bucket = self._make_one(properties=properties)
11481148
self.assertEqual(bucket.project_number, PROJECT_NUMBER)
11491149

1150+
def test_retention_policy_effective_time_policy_missing(self):
1151+
bucket = self._make_one()
1152+
self.assertIsNone(bucket.retention_policy_effective_time)
1153+
1154+
def test_retention_policy_effective_time_et_missing(self):
1155+
properties = {
1156+
'retentionPolicy': {
1157+
},
1158+
}
1159+
bucket = self._make_one(properties=properties)
1160+
1161+
self.assertIsNone(bucket.retention_policy_effective_time)
1162+
1163+
def test_retention_policy_effective_time(self):
1164+
import datetime
1165+
from google.cloud._helpers import _datetime_to_rfc3339
1166+
from google.cloud._helpers import UTC
1167+
1168+
effective_time = datetime.datetime.utcnow().replace(tzinfo=UTC)
1169+
properties = {
1170+
'retentionPolicy': {
1171+
'effectiveTime': _datetime_to_rfc3339(effective_time),
1172+
},
1173+
}
1174+
bucket = self._make_one(properties=properties)
1175+
1176+
self.assertEqual(
1177+
bucket.retention_policy_effective_time, effective_time)
1178+
1179+
def test_retention_policy_locked_missing(self):
1180+
bucket = self._make_one()
1181+
self.assertFalse(bucket.retention_policy_locked)
1182+
1183+
def test_retention_policy_locked_false(self):
1184+
properties = {
1185+
'retentionPolicy': {
1186+
'isLocked': False,
1187+
},
1188+
}
1189+
bucket = self._make_one(properties=properties)
1190+
self.assertFalse(bucket.retention_policy_locked)
1191+
1192+
def test_retention_policy_locked_true(self):
1193+
properties = {
1194+
'retentionPolicy': {
1195+
'isLocked': True,
1196+
},
1197+
}
1198+
bucket = self._make_one(properties=properties)
1199+
self.assertTrue(bucket.retention_policy_locked)
1200+
1201+
def test_retention_period_getter_policymissing(self):
1202+
bucket = self._make_one()
1203+
1204+
self.assertIsNone(bucket.retention_period)
1205+
1206+
def test_retention_period_getter_pr_missing(self):
1207+
properties = {
1208+
'retentionPolicy': {
1209+
},
1210+
}
1211+
bucket = self._make_one(properties=properties)
1212+
1213+
self.assertIsNone(bucket.retention_period)
1214+
1215+
def test_retention_period_getter(self):
1216+
period = 86400 * 100 # 100 days
1217+
properties = {
1218+
'retentionPolicy': {
1219+
'retentionPeriod': str(period),
1220+
},
1221+
}
1222+
bucket = self._make_one(properties=properties)
1223+
1224+
self.assertEqual(bucket.retention_period, period)
1225+
1226+
def test_retention_period_setter(self):
1227+
period = 86400 * 100 # 100 days
1228+
bucket = self._make_one()
1229+
1230+
bucket.retention_period = period
1231+
1232+
self.assertEqual(
1233+
bucket._properties['retentionPolicy']['retentionPeriod'],
1234+
str(period))
1235+
11501236
def test_self_link(self):
11511237
SELF_LINK = 'http://example.com/self/'
11521238
properties = {'selfLink': SELF_LINK}

0 commit comments

Comments
 (0)