From 80700b2445774589277afac4d52ef294bbb9d1eb Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Fri, 28 Sep 2018 16:43:44 -0700 Subject: [PATCH] Use 0-prereqs, in prep for skeleton sync --- .../utils/test_ordered_task_preparation.py | 39 +++++++++++++++++-- trinity/utils/datastructures.py | 8 ++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/tests/trinity/utils/test_ordered_task_preparation.py b/tests/trinity/utils/test_ordered_task_preparation.py index 6679d1a21c..fa7c409c16 100644 --- a/tests/trinity/utils/test_ordered_task_preparation.py +++ b/tests/trinity/utils/test_ordered_task_preparation.py @@ -20,6 +20,10 @@ async def wait(coro, timeout=DEFAULT_TIMEOUT): return await asyncio.wait_for(coro, timeout=timeout) +class NoPrerequisites(Enum): + pass + + class OnePrereq(Enum): one = auto() @@ -187,6 +191,17 @@ def test_reregister_duplicates(): ti.register_tasks((2, )) +@pytest.mark.asyncio +async def test_no_prereq_tasks(): + ti = OrderedTaskPreparation(NoPrerequisites, identity, lambda x: x - 1) + ti.set_finished_dependency(1) + ti.register_tasks((2, 3)) + + # with no prerequisites, tasks are *immediately* finished, as long as they are in order + finished = await wait(ti.ready_tasks()) + assert finished == (2, 3) + + @pytest.mark.asyncio async def test_register_out_of_order(): ti = OrderedTaskPreparation(OnePrereq, identity, lambda x: x - 1, accept_dangling_tasks=True) @@ -207,13 +222,29 @@ async def test_register_out_of_order(): assert finished == (2, 3, 4, 5) -def test_empty_enum(): +@pytest.mark.asyncio +async def test_no_prereq_tasks_out_of_order(): + ti = OrderedTaskPreparation( + NoPrerequisites, + identity, + lambda x: x - 1, + accept_dangling_tasks=True, + ) + ti.set_finished_dependency(1) + ti.register_tasks((4, 5)) - class NoPrerequisites(Enum): + try: + finished = await wait(ti.ready_tasks()) + except asyncio.TimeoutError: pass + else: + assert False, f"No steps should be ready, but got {finished!r}" - with pytest.raises(ValidationError): - OrderedTaskPreparation(NoPrerequisites, identity, lambda x: x - 1) + ti.register_tasks((2, 3)) + + # with no prerequisites, tasks are *immediately* finished, as long as they are in order + finished = await wait(ti.ready_tasks()) + assert finished == (2, 3, 4, 5) @pytest.mark.asyncio diff --git a/trinity/utils/datastructures.py b/trinity/utils/datastructures.py index 91a26db0fe..21e05fd281 100644 --- a/trinity/utils/datastructures.py +++ b/trinity/utils/datastructures.py @@ -301,10 +301,6 @@ class BaseTaskPrerequisites(Generic[TTask, TPrerequisite]): @classmethod def from_enum(cls, prereqs: Type[TPrerequisite]) -> 'Type[BaseTaskPrerequisites[Any, Any]]': - - if len(prereqs) < 1: - raise ValidationError("There must be at least one prerequisite to track completions") - return type('CompletionFor' + prereqs.__name__, (cls, ), dict(_prereqs=prereqs)) def __init__(self, task: TTask) -> None: @@ -540,6 +536,10 @@ def register_tasks(self, tasks: Tuple[TTask, ...]) -> None: self._unready.add(task_id) self._dependencies[dependency_id].add(task_id) + if prereq_tracker.is_complete and self._is_ready(prereq_tracker.task): + # this is possible for tasks with 0 prerequisites (useful for pure ordering) + self._mark_complete(task_id) + def finish_prereq(self, prereq: TPrerequisite, tasks: Tuple[TTask, ...]) -> None: """For every task in tasks, mark the given prerequisite as completed""" if len(self._tasks) == 0: