Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit 0300121

Browse files
committed
feat: expose read-only 'Instance.create_time' property
From new field in the 'Instance' proto, added in PR #449.
1 parent a99bf88 commit 0300121

File tree

2 files changed

+48
-11
lines changed

2 files changed

+48
-11
lines changed

google/cloud/bigtable/instance.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,18 @@
1515
"""User-friendly container for Google Cloud Bigtable Instance."""
1616

1717
import re
18+
import warnings
1819

19-
from google.cloud.bigtable.app_profile import AppProfile
20-
from google.cloud.bigtable.cluster import Cluster
21-
from google.cloud.bigtable.table import Table
22-
20+
from google.api_core.datetime_helpers import DatetimeWithNanoseconds
21+
from google.api_core.exceptions import NotFound
22+
from google.iam.v1 import options_pb2 # type: ignore
2323
from google.protobuf import field_mask_pb2
2424

2525
from google.cloud.bigtable_admin_v2.types import instance
26-
27-
from google.iam.v1 import options_pb2 # type: ignore
28-
29-
from google.api_core.exceptions import NotFound
30-
26+
from google.cloud.bigtable.app_profile import AppProfile
27+
from google.cloud.bigtable.cluster import Cluster
3128
from google.cloud.bigtable.policy import Policy
32-
33-
import warnings
29+
from google.cloud.bigtable.table import Table
3430

3531
_INSTANCE_NAME_RE = re.compile(
3632
r"^projects/(?P<project>[^/]+)/" r"instances/(?P<instance_id>[a-z][-a-z0-9]*)$"
@@ -115,6 +111,7 @@ def __init__(
115111
self.type_ = instance_type
116112
self.labels = labels
117113
self._state = _state
114+
self._create_time = None
118115

119116
def _update_from_pb(self, instance_pb):
120117
"""Refresh self from the server-provided protobuf.
@@ -126,6 +123,12 @@ def _update_from_pb(self, instance_pb):
126123
self.type_ = instance_pb.type_
127124
self.labels = dict(instance_pb.labels)
128125
self._state = instance_pb.state
126+
if instance_pb.create_time is not None:
127+
self._create_time = DatetimeWithNanoseconds.from_pb(
128+
instance_pb.create_time
129+
)
130+
else:
131+
self._create_time = None
129132

130133
@classmethod
131134
def from_pb(cls, instance_pb, client):
@@ -208,6 +211,16 @@ def state(self):
208211
"""
209212
return self._state
210213

214+
@property
215+
def create_time(self):
216+
"""Timestamp when the instance was created.
217+
218+
:rtype:
219+
:class:`~google.api_core.datetime_helpers.DatetimeWithNanoseconds`
220+
or ``None``
221+
"""
222+
return self._create_time
223+
211224
def __eq__(self, other):
212225
if not isinstance(other, self.__class__):
213226
return NotImplemented

tests/unit/test_instance.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def test_constructor_defaults(self):
7272
self.assertIsNone(instance.labels)
7373
self.assertIs(instance._client, client)
7474
self.assertIsNone(instance.state)
75+
self.assertIsNone(instance.create_time)
7576

7677
def test_constructor_non_default(self):
7778
from google.cloud.bigtable import enums
@@ -95,19 +96,34 @@ def test_constructor_non_default(self):
9596
self.assertEqual(instance.labels, labels)
9697
self.assertIs(instance._client, client)
9798
self.assertEqual(instance.state, state)
99+
self.assertIsNone(instance.create_time)
100+
101+
@staticmethod
102+
def _make_timestamp_pb():
103+
import datetime
104+
from google.protobuf import timestamp_pb2
105+
106+
now = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
107+
seconds = int(now.timestamp())
108+
nanos = int((now.timestamp() - seconds) * 1e9)
109+
return timestamp_pb2.Timestamp(seconds=seconds, nanos=nanos)
98110

99111
def test__update_from_pb_success(self):
112+
import datetime
113+
from google.api_core.datetime_helpers import DatetimeWithNanoseconds
100114
from google.cloud.bigtable_admin_v2.types import instance as data_v2_pb2
101115
from google.cloud.bigtable import enums
102116

103117
instance_type = data_v2_pb2.Instance.Type.PRODUCTION
104118
state = enums.Instance.State.READY
119+
timestamp = self._make_timestamp_pb()
105120
# todo type to type_?
106121
instance_pb = data_v2_pb2.Instance(
107122
display_name=self.DISPLAY_NAME,
108123
type_=instance_type,
109124
labels=self.LABELS,
110125
state=state,
126+
create_time=timestamp,
111127
)
112128

113129
instance = self._make_one(None, None)
@@ -119,6 +135,8 @@ def test__update_from_pb_success(self):
119135
self.assertEqual(instance.type_, instance_type)
120136
self.assertEqual(instance.labels, self.LABELS)
121137
self.assertEqual(instance._state, state)
138+
expected_dt = DatetimeWithNanoseconds.from_timestamp_pb(timestamp)
139+
self.assertEqual( instance.create_time, expected_dt )
122140

123141
def test__update_from_pb_success_defaults(self):
124142
from google.cloud.bigtable_admin_v2.types import instance as data_v2_pb2
@@ -134,6 +152,7 @@ def test__update_from_pb_success_defaults(self):
134152
self.assertEqual(instance.display_name, self.DISPLAY_NAME)
135153
self.assertEqual(instance.type_, enums.Instance.Type.UNSPECIFIED)
136154
self.assertFalse(instance.labels)
155+
self.assertIsNone(instance.create_time)
137156

138157
def test__update_from_pb_no_display_name(self):
139158
from google.cloud.bigtable_admin_v2.types import instance as data_v2_pb2
@@ -145,6 +164,7 @@ def test__update_from_pb_no_display_name(self):
145164
instance._update_from_pb(instance_pb)
146165

147166
def test_from_pb_success(self):
167+
from google.api_core.datetime_helpers import DatetimeWithNanoseconds
148168
from google.cloud.bigtable_admin_v2.types import instance as data_v2_pb2
149169
from google.cloud.bigtable import enums
150170

@@ -154,12 +174,14 @@ def test_from_pb_success(self):
154174
)
155175
instance_type = enums.Instance.Type.PRODUCTION
156176
state = enums.Instance.State.READY
177+
timestamp = self._make_timestamp_pb()
157178
instance_pb = data_v2_pb2.Instance(
158179
name=self.INSTANCE_NAME,
159180
display_name=self.INSTANCE_ID,
160181
type_=instance_type,
161182
labels=self.LABELS,
162183
state=state,
184+
created_time=timestamp,
163185
)
164186

165187
klass = self._get_target_class()
@@ -171,6 +193,8 @@ def test_from_pb_success(self):
171193
self.assertEqual(instance.type_, instance_type)
172194
self.assertEqual(instance.labels, self.LABELS)
173195
self.assertEqual(instance._state, state)
196+
expected_dt = DatetimeWithNanoseconds.from_timestamp_pb(timestamp)
197+
self.assertEqual( instance.create_time, expected_dt )
174198

175199
def test_from_pb_bad_instance_name(self):
176200
from google.cloud.bigtable_admin_v2.types import instance as data_v2_pb2

0 commit comments

Comments
 (0)