Skip to content

Commit 8e053cf

Browse files
author
Chris Rossi
authored
fix: support nested sequences in parallel yield for tasklets (#358)
This adds backwards compatibility with the legacy code. Fixes #349.
1 parent 42093bd commit 8e053cf

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

packages/google-cloud-ndb/google/cloud/ndb/tasklets.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,15 @@ class _MultiFuture(Future):
406406

407407
def __init__(self, dependencies):
408408
super(_MultiFuture, self).__init__()
409-
self._dependencies = dependencies
410-
409+
futures = []
411410
for dependency in dependencies:
411+
if isinstance(dependency, (list, tuple)):
412+
dependency = _MultiFuture(dependency)
413+
futures.append(dependency)
414+
415+
self._dependencies = futures
416+
417+
for dependency in futures:
412418
dependency.add_done_callback(self._dependency_done)
413419

414420
if not dependencies:

packages/google-cloud-ndb/tests/system/test_crud.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,50 @@ def get_two_entities():
208208
assert entity2.bar == "naan"
209209

210210

211+
@pytest.mark.usefixtures("client_context")
212+
def test_retrieve_entities_in_parallel_nested(ds_entity):
213+
"""Regression test for #357.
214+
215+
https://github.com/googleapis/python-ndb/issues/357
216+
"""
217+
entity1_id = test_utils.system.unique_resource_id()
218+
ds_entity(KIND, entity1_id, foo=42, bar="none")
219+
entity2_id = test_utils.system.unique_resource_id()
220+
ds_entity(KIND, entity2_id, foo=65, bar="naan")
221+
entity3_id = test_utils.system.unique_resource_id()
222+
ds_entity(KIND, entity3_id, foo=66, bar="route")
223+
224+
class SomeKind(ndb.Model):
225+
foo = ndb.IntegerProperty()
226+
bar = ndb.StringProperty()
227+
228+
key1 = ndb.Key(KIND, entity1_id)
229+
key2 = ndb.Key(KIND, entity2_id)
230+
key3 = ndb.Key(KIND, entity3_id)
231+
232+
@ndb.tasklet
233+
def get_two_entities():
234+
entity1, (entity2, entity3) = yield (
235+
key1.get_async(),
236+
[key2.get_async(), key3.get_async()],
237+
)
238+
raise ndb.Return(entity1, entity2, entity3)
239+
240+
entity1, entity2, entity3 = get_two_entities().result()
241+
242+
assert isinstance(entity1, SomeKind)
243+
assert entity1.foo == 42
244+
assert entity1.bar == "none"
245+
246+
assert isinstance(entity2, SomeKind)
247+
assert entity2.foo == 65
248+
assert entity2.bar == "naan"
249+
250+
assert isinstance(entity3, SomeKind)
251+
assert entity3.foo == 66
252+
assert entity3.bar == "route"
253+
254+
211255
@pytest.mark.usefixtures("client_context")
212256
def test_insert_entity(dispose_of, ds_client):
213257
class SomeKind(ndb.Model):

packages/google-cloud-ndb/tests/unit/test_tasklets.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,15 @@ def test_no_dependencies():
458458
future = tasklets._MultiFuture(())
459459
assert future.result() == ()
460460

461+
@staticmethod
462+
def test_nested():
463+
dependencies = [tasklets.Future() for _ in range(3)]
464+
future = tasklets._MultiFuture((dependencies[0], dependencies[1:]))
465+
for i, dependency in enumerate(dependencies):
466+
dependency.set_result(i)
467+
468+
assert future.result() == (0, (1, 2))
469+
461470

462471
class Test__get_return_value:
463472
@staticmethod

0 commit comments

Comments
 (0)