Skip to content

Commit 3c7054e

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

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
@@ -966,6 +966,21 @@ def cors(self, entries):
966966
"""
967967
self._patch_property('cors', entries)
968968

969+
default_event_based_hold = _scalar_property('defaultEventBasedHold')
970+
"""Are uploaded objects automatically placed under an even-based hold?
971+
972+
If True, uploaded objects will be placed under an event-based hold to
973+
be released at a future time. When released an object will then begin
974+
the retention period determined by the policy retention period for the
975+
object bucket.
976+
977+
See https://cloud.google.com/storage/docs/json_api/v1/buckets
978+
979+
If the property is not set locally, returns ``None``.
980+
981+
:rtype: bool or ``NoneType``
982+
"""
983+
969984
@property
970985
def default_kms_key_name(self):
971986
"""Retrieve / set default KMS encryption key for objects in the bucket.
@@ -1273,6 +1288,64 @@ def project_number(self):
12731288
if project_number is not None:
12741289
return int(project_number)
12751290

1291+
@property
1292+
def retention_policy_effective_time(self):
1293+
"""Retrieve the effective time of the bucket's retention policy.
1294+
1295+
:rtype: datetime.datetime or ``NoneType``
1296+
:returns: point-in time at which the bucket's retention policy is
1297+
effective, or ``None`` if the property is not
1298+
set locally.
1299+
"""
1300+
policy = self._properties.get('retentionPolicy')
1301+
if policy is not None:
1302+
timestamp = policy.get('effectiveTime')
1303+
if timestamp is not None:
1304+
return _rfc3339_to_datetime(timestamp)
1305+
1306+
@property
1307+
def retention_policy_locked(self):
1308+
"""Retrieve whthere the bucket's retention policy is locked.
1309+
1310+
:rtype: bool
1311+
:returns: True if the bucket's policy is locked, or else False
1312+
if the policy is not locked, or the property is not
1313+
set locally.
1314+
"""
1315+
policy = self._properties.get('retentionPolicy')
1316+
if policy is not None:
1317+
return policy.get('isLocked')
1318+
1319+
@property
1320+
def retention_period(self):
1321+
"""Retrieve or set the retention period for items in the bucket.
1322+
1323+
:rtype: int or ``NoneType``
1324+
:returns: number of seconds to retain items after upload or release
1325+
from event-based lock, or ``None`` if the property is not
1326+
set locally.
1327+
"""
1328+
policy = self._properties.get('retentionPolicy')
1329+
if policy is not None:
1330+
period = policy.get('retentionPeriod')
1331+
if period is not None:
1332+
return int(period)
1333+
1334+
@retention_period.setter
1335+
def retention_period(self, value):
1336+
"""Set the retention period for items in the bucket.
1337+
1338+
:type value: int
1339+
:param value:
1340+
number of seconds to retain items after upload or release from
1341+
event-based lock.
1342+
1343+
:raises ValueError: if the bucket's retention policy is locked.
1344+
"""
1345+
policy = self._properties.setdefault('retentionPolicy', {})
1346+
policy['retentionPeriod'] = str(value)
1347+
self._patch_property('retentionPolicy', policy)
1348+
12761349
@property
12771350
def self_link(self):
12781351
"""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
@@ -1488,6 +1488,92 @@ def test_project_number_string_val(self):
14881488
bucket = self._make_one(properties=properties)
14891489
self.assertEqual(bucket.project_number, PROJECT_NUMBER)
14901490

1491+
def test_retention_policy_effective_time_policy_missing(self):
1492+
bucket = self._make_one()
1493+
self.assertIsNone(bucket.retention_policy_effective_time)
1494+
1495+
def test_retention_policy_effective_time_et_missing(self):
1496+
properties = {
1497+
'retentionPolicy': {
1498+
},
1499+
}
1500+
bucket = self._make_one(properties=properties)
1501+
1502+
self.assertIsNone(bucket.retention_policy_effective_time)
1503+
1504+
def test_retention_policy_effective_time(self):
1505+
import datetime
1506+
from google.cloud._helpers import _datetime_to_rfc3339
1507+
from google.cloud._helpers import UTC
1508+
1509+
effective_time = datetime.datetime.utcnow().replace(tzinfo=UTC)
1510+
properties = {
1511+
'retentionPolicy': {
1512+
'effectiveTime': _datetime_to_rfc3339(effective_time),
1513+
},
1514+
}
1515+
bucket = self._make_one(properties=properties)
1516+
1517+
self.assertEqual(
1518+
bucket.retention_policy_effective_time, effective_time)
1519+
1520+
def test_retention_policy_locked_missing(self):
1521+
bucket = self._make_one()
1522+
self.assertFalse(bucket.retention_policy_locked)
1523+
1524+
def test_retention_policy_locked_false(self):
1525+
properties = {
1526+
'retentionPolicy': {
1527+
'isLocked': False,
1528+
},
1529+
}
1530+
bucket = self._make_one(properties=properties)
1531+
self.assertFalse(bucket.retention_policy_locked)
1532+
1533+
def test_retention_policy_locked_true(self):
1534+
properties = {
1535+
'retentionPolicy': {
1536+
'isLocked': True,
1537+
},
1538+
}
1539+
bucket = self._make_one(properties=properties)
1540+
self.assertTrue(bucket.retention_policy_locked)
1541+
1542+
def test_retention_period_getter_policymissing(self):
1543+
bucket = self._make_one()
1544+
1545+
self.assertIsNone(bucket.retention_period)
1546+
1547+
def test_retention_period_getter_pr_missing(self):
1548+
properties = {
1549+
'retentionPolicy': {
1550+
},
1551+
}
1552+
bucket = self._make_one(properties=properties)
1553+
1554+
self.assertIsNone(bucket.retention_period)
1555+
1556+
def test_retention_period_getter(self):
1557+
period = 86400 * 100 # 100 days
1558+
properties = {
1559+
'retentionPolicy': {
1560+
'retentionPeriod': str(period),
1561+
},
1562+
}
1563+
bucket = self._make_one(properties=properties)
1564+
1565+
self.assertEqual(bucket.retention_period, period)
1566+
1567+
def test_retention_period_setter(self):
1568+
period = 86400 * 100 # 100 days
1569+
bucket = self._make_one()
1570+
1571+
bucket.retention_period = period
1572+
1573+
self.assertEqual(
1574+
bucket._properties['retentionPolicy']['retentionPeriod'],
1575+
str(period))
1576+
14911577
def test_self_link(self):
14921578
SELF_LINK = 'http://example.com/self/'
14931579
properties = {'selfLink': SELF_LINK}

0 commit comments

Comments
 (0)