8000 fix: repair implementation of `Client.reserve_ids` (#76) · samkenxstream/python-datastore@7df727d · GitHub 8000
[go: up one dir, main page]

Skip to content

Commit 7df727d

Browse files
author
Chris Rossi
authored
fix: repair implementation of Client.reserve_ids (googleapis#76)
`Client.reserve_ids` has been reimplemented in a way that should be a lot more useful, and has been renamed `Client_reserve_ids_sequential`, leaving the old name as a deprecated alias. `Client.reserve_ids_multi` has been added, which takes sequence of complete keys to reserve. Fixes googleapis#37
1 parent c947ad7 commit 7df727d

File tree

3 files changed

+303
-41
lines changed

3 files changed

+303
-41
lines changed

google/cloud/datastore/client.py

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"""Convenience wrapper for invoking APIs/factories w/ a project."""
1515

1616
import os
17+
import warnings
1718

1819
import google.api_core.client_options
1920
from google.auth.credentials import AnonymousCredentials
@@ -816,11 +817,18 @@ def do_something(entity):
816817
kwargs["namespace"] = self.namespace
817818
return Query(self, **kwargs)
818819

819-
def reserve_ids(self, complete_key, num_ids, retry=None, timeout=None):
820-
"""Reserve a list of IDs from a complete key.
820+
def reserve_ids_sequential(self, complete_key, num_ids, retry=None, timeout=None):
821+
"""Reserve a list of IDs sequentially from a complete key.
822+
823+
This will reserve the key passed as `complete_key` as well as
824+
additional keys derived by incrementing the last ID in the path of
825+
`complete_key` sequentially to obtain the number of keys specified in
826+
`num_ids`.
821827
822828
:type complete_key: :class:`google.cloud.datastore.key.Key`
823-
:param complete_key: Complete key to use as base for reserved IDs.
829+
:param complete_key:
830+
Complete key to use as base for reserved IDs. Key must use a
831+
numeric ID and not a string name.
824832
825833
:type num_ids: int
826834
:param num_ids: The number of IDs to reserve.
@@ -844,16 +852,75 @@ def reserve_ids(self, complete_key, num_ids, retry=None, timeout=None):
844852
if complete_key.is_partial:
845853
raise ValueError(("Key is not Complete.", complete_key))
846854

855+
if complete_key.id is None:
856+
raise ValueError(("Key must use numeric id.", complete_key))
857+
847858
if not isinstance(num_ids, int):
848859
raise ValueError(("num_ids is not a valid integer.", num_ids))
849860

861+
key_class = type(complete_key)
862+
namespace = complete_key._namespace
863+
project = complete_key._project
864+
flat_path = list(complete_key._flat_path[:-1])
865+
start_id = complete_key._flat_path[-1]
866+
867+
key_pbs = []
868+
for id in range(start_id, start_id + num_ids):
869+
path = flat_path + [id]
870+
key = key_class(*path, project=project, namespace=namespace)
871+
key_pbs.append(key.to_protobuf())
872+
850873
kwargs = _make_retry_timeout_kwargs(retry, timeout)
874+
self._datastore_api.reserve_ids(complete_key.project, key_pbs, **kwargs)
875+
876+
return None
877+
878+
def reserve_ids(self, complete_key, num_ids, retry=None, timeout=None):
879+
"""Reserve a list of IDs sequentially from a complete key.
851880
852-
complete_key_pb = complete_key.to_protobuf()
853-
complete_key_pbs = [complete_key_pb] * num_ids
881+
DEPRECATED. Alias for :meth:`reserve_ids_sequential`.
854882
855-
self._datastore_api.reserve_ids(
856-
complete_key.project, complete_key_pbs, **kwargs
883+
Please use either :meth:`reserve_ids_multi` (recommended) or
884+
:meth:`reserve_ids_sequential`.
885+
"""
886+
message = (
887+
"Client.reserve_ids is deprecated. Please use "
888+
"Client.reserve_ids_multi or Client.reserve_ids_sequential",
857889
)
890+
warnings.warn(message, DeprecationWarning)
891+
return self.reserve_ids_sequential(
892+
complete_key, num_ids, retry=retry, timeout=timeout
893+
)
894+
895+
def reserve_ids_multi(self, complete_keys, retry=None, timeout=None):
896+
"""Reserve IDs from a list of complete keys.
897+
898+
:type complete_keys: `list` of :class:`google.cloud.datastore.key.Key`
899+
:param complete_keys:
900+
Complete keys for which to reserve IDs.
901+
902+
:type retry: :class:`google.api_core.retry.Retry`
903+
:param retry:
904+
A retry object used to retry requests. If ``None`` is specified,
905+
requests will be retried using a default configuration.
906+
907+
:type timeout: float
908+
:param timeout:
909+
Time, in seconds, to wait for the request to complete.
910+
Note that if ``retry`` is specified, the timeout applies
911+
to each individual attempt.
912+
913+
:rtype: class:`NoneType`
914+
:returns: None
915+
:raises: :class:`ValueError` if any of `complete_keys`` is not a
916+
Complete key.
917+
"""
918+
for complete_key in complete_keys:
919+
if complete_key.is_partial:
920+
raise ValueError(("Key is not Complete.", complete_key))
921+
922+
kwargs = _make_retry_timeout_kwargs(retry, timeout)
923+
key_pbs = [key.to_protobuf() for key in complete_keys]
924+
self._datastore_api.reserve_ids(complete_keys[0].project, key_pbs, **kwargs)
858925

859926
return None

tests/system/test_system.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import datetime
1616
import os
1717
import unittest
18+
import warnings
1819

1920
import requests
2021
import six
@@ -102,6 +103,32 @@ def test_allocate_ids(self):
102103
self.assertEqual(len(unique_ids), num_ids)
103104

104105

106+
class TestDatastoreReserveIDs(TestDatastore):
107+
def test_reserve_ids_sequential(self):
108+
# Smoke test to make sure it doesn't blow up. No return value or
109+
# verifiable side effect to verify.
110+
num_ids = 10
111+
Config.CLIENT.reserve_ids_sequential(Config.CLIENT.key("Kind", 1234), num_ids)
112+
113+
def test_reserve_ids(self):
114+
with warnings.catch_warnings(record=True) as warned:
115+
num_ids = 10
116+
Config.CLIENT.reserve_ids(Config.CLIENT.key("Kind", 1234), num_ids)
117+
118+
warned = [
119+
warning
120+
for warning in warned
121+
if "reserve_ids_sequential" in str(warning.message)
122+
]
123+
assert len(warned) == 1
124+
125+
def test_reserve_ids_multi(self):
126+
# Smoke test to make sure it doesn't blow up. No return value or
127+
# verifiable side effect to verify.
128+
keys = [Config.CLIENT.key("KIND", 1234), Config.CLIENT.key("KIND", 1235)]
129+
Config.CLIENT.reserve_ids_multi(keys)
130+
131+
105132
class TestDatastoreSave(TestDatastore):
106133
@classmethod
107134
def setUpClass(cls):

0 commit comments

Comments
 (0)
0