Skip to content

Commit 5e66a73

Browse files
authored
fix: hash snapshots using correct type for 'update_time' (#467)
Document that 'DocumentSnapshot.create_time' and 'DocumentSnapshot.update_time' are instances of 'proto.datetime_helpers.DatetimeWithNanoseconds'. Closes #398. Closes #391.
1 parent ddcb099 commit 5e66a73

File tree

3 files changed

+23
-14
lines changed

3 files changed

+23
-14
lines changed

google/cloud/firestore_v1/base_document.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,11 @@ class DocumentSnapshot(object):
342342
exists (bool):
343343
Indicates if the document existed at the time the snapshot was
344344
retrieved.
345-
read_time (:class:`google.protobuf.timestamp_pb2.Timestamp`):
345+
read_time (:class:`proto.datetime_helpers.DatetimeWithNanoseconds`):
346346
The time that this snapshot was read from the server.
347-
create_time (:class:`google.protobuf.timestamp_pb2.Timestamp`):
347+
create_time (:class:`proto.datetime_helpers.DatetimeWithNanoseconds`):
348348
The time that this document was created.
349-
update_time (:class:`google.protobuf.timestamp_pb2.Timestamp`):
349+
update_time (:class:`proto.datetime_helpers.DatetimeWithNanoseconds`):
350350
The time that this document was last updated.
351351
"""
352352

@@ -368,9 +368,7 @@ def __eq__(self, other):
368368
return self._reference == other._reference and self._data == other._data
369369

370370
def __hash__(self):
371-
seconds = int(self.update_time.timestamp())
372-
nanos = self.update_time.nanosecond
373-
return hash(self._reference) + hash(seconds) + hash(nanos)
371+
return hash(self._reference) + hash(self.update_time)
374372

375373
@property
376374
def _client(self):

tests/system/test_system.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,8 +1584,7 @@ def test_repro_429(client, cleanup):
15841584
now = datetime.datetime.utcnow().replace(tzinfo=UTC)
15851585
collection = client.collection("repro-429" + UNIQUE_RESOURCE_ID)
15861586

1587-
document_ids = [f"doc-{doc_id:02d}" for doc_id in range(30)]
1588-
for document_id in document_ids:
1587+
for document_id in [f"doc-{doc_id:02d}" for doc_id in range(30)]:
15891588
data = {"now": now, "paymentId": None}
15901589
_, document = collection.add(data, document_id)
15911590
cleanup(document.delete)
@@ -1601,3 +1600,17 @@ def test_repro_429(client, cleanup):
16011600

16021601
for snapshot in query2.stream():
16031602
print(f"id: {snapshot.id}")
1603+
1604+
1605+
def test_repro_391(client, cleanup):
1606+
# See: https://github.com/googleapis/python-firestore/issues/391
1607+
now = datetime.datetime.utcnow().replace(tzinfo=UTC)
1608+
collection = client.collection("repro-391" + UNIQUE_RESOURCE_ID)
1609+
1610+
document_ids = [f"doc-{doc_id:02d}" for doc_id in range(30)]
1611+
1612+
for document_id in [f"doc-{doc_id:02d}" for doc_id in range(30)]:
1613+
data = {"now": now}
1614+
_, document = collection.add(data, document_id)
1615+
1616+
assert len(set(collection.stream())) == len(document_ids)

tests/unit/v1/test_base_document.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import datetime
1516
import unittest
1617

1718
import mock
1819
from proto.datetime_helpers import DatetimeWithNanoseconds
19-
from google.protobuf import timestamp_pb2
2020

2121

2222
class TestBaseDocumentReference(unittest.TestCase):
@@ -274,15 +274,13 @@ def test___hash__(self):
274274
client.__hash__.return_value = 234566789
275275
reference = self._make_reference("hi", "bye", client=client)
276276
data = {"zoop": 83}
277-
update_time = DatetimeWithNanoseconds.from_timestamp_pb(
278-
timestamp_pb2.Timestamp(seconds=123456, nanos=123456789)
277+
update_time = DatetimeWithNanoseconds(
278+
2021, 10, 4, 17, 43, 27, nanosecond=123456789, tzinfo=datetime.timezone.utc
279279
)
280280
snapshot = self._make_one(
281281
reference, data, True, None, mock.sentinel.create_time, update_time
282282
)
283-
self.assertEqual(
284-
hash(snapshot), hash(reference) + hash(123456) + hash(123456789)
285-
)
283+
self.assertEqual(hash(snapshot), hash(reference) + hash(update_time))
286284

287285
def test__client_property(self):
288286
reference = self._make_reference(

0 commit comments

Comments
 (0)