Example #1
0
def test_topological_queue_two_dependent_nodes():
    graph = basic.DependencyGraph(initial_dependencies={
        "A": set(),
        "B": {"A"}
    })
    queue = basic.TopologicalQueue(graph)
    assert not queue.empty()
    assert len(queue) == 2
    assert queue.ready_set() == {"A"}
    now_ready = queue.completed("A")

    # There was a bug that resulted in the LHS of the following actually
    # being equal to an empty set
    assert graph.dependency_dict["B"] == {"A"}

    assert len(queue) == 1
    assert queue.ready_set() == {"B"}
    assert now_ready == {"B"}
    now_ready = queue.completed("B")
    assert len(queue) == 0
    assert queue.ready_set() == set()
    assert queue.empty()
    assert now_ready == set()

    assert graph.dependency_dict["A"] == set()
    # There was a bug that resulted in the LHS of the following actually
    # being equal to an empty set
    assert graph.dependency_dict["B"] == {"A"}
Example #2
0
async def async_compute_concurrent_simple(graph):

    logger.debug("enter, graph.name=%s", graph.name)

    task_graph = graph.decorate(ensure_coroutine)
    queue = basic.TopologicalQueue(task_graph)
    ready_tasks = create_tasks(queue.ready_set())

    while len(ready_tasks):
        assert not queue.empty()
        # 'pending' could be replaced with 'ready_tasks' here
        # and the line after (ready_tasks -= completed) could be removed
        completed, pending = await asyncio.wait(
            ready_tasks, return_when=asyncio.FIRST_COMPLETED)
        raise_task_exceptions(completed)
        ready_tasks -= completed
        for completed_task in completed:
            now_ready = queue.completed(completed_task.get_coro())
            logger.debug("now_ready=%s", now_ready)
            ready_tasks |= create_tasks(now_ready)
            logger.debug("ready_tasks=%s", now_ready)

    assert len(ready_tasks) == 0
    assert queue.empty(), f"queue.dependency_dict: {queue.dependency_dict}"

    logger.debug("exit, graph.name=%s", graph.name)
Example #3
0
def test_topological_queue_two_independent_nodes():
    graph = basic.DependencyGraph(initial_dependencies={"A": {}, "B": {}})
    queue = basic.TopologicalQueue(graph)
    assert not queue.empty()
    assert queue.ready_set() == {"A", "B"}
    now_ready = queue.completed("B")
    assert queue.ready_set() == {"A"}
    # Nothing depends on "A" so its completion does not activate any
    # nodes
    assert now_ready == set()
Example #4
0
def test_topological_queue_diamond():
    queue = basic.TopologicalQueue(
        basic.DependencyGraph(initial_dependencies={
            "A": {},
            "B": {"A"},
            "C": {"A"},
            "D": {"B", "C"}
        }))

    assert not queue.empty()
    assert len(queue) == 4
    ready_set_a = queue.ready_set()
    assert ready_set_a == {"A"}

    now_ready_a = queue.completed("A")
    assert ready_set_a == {"A"}
    ready_set_bc = queue.ready_set()
    assert ready_set_bc == {"B", "C"}
    assert now_ready_a == {"B", "C"}
    assert len(queue) == 3
    assert not queue.empty()

    now_ready_b = queue.completed("B")
    assert queue.ready_set() == {"C"}
    assert now_ready_b == set()
    assert len(queue) == 2
    assert not queue.empty()

    # Make sure this didn't change under our feet
    assert now_ready_a == {"B", "C"}

    now_ready = queue.completed("C")
    assert queue.ready_set() == {"D"}
    assert now_ready == {"D"}
    assert len(queue) == 1
    assert not queue.empty()

    with pytest.raises(KeyError):
        queue.completed("C")

    now_ready = queue.completed("D")
    assert queue.ready_set() == set()
    assert now_ready == set()
    assert len(queue) == 0
    assert queue.empty()
Example #5
0
async def async_compute_concurrent(graph):

    logger.debug("enter, graph.name=%s", graph.name)

    queue = basic.TopologicalQueue(graph)
    ready_set = queue.ready_set()

    logger.debug("ready_set: %s", ready_set)
    callables, running_tasks = prepare_ready_set(ready_set)

    while not queue.empty():

        while len(callables):
            the_callable = callables.pop()
            the_callable()
            now_ready = queue.completed(the_callable)
            new_callables, new_tasks = prepare_ready_set(now_ready)
            callables |= new_callables
            running_tasks |= new_tasks

        while len(running_tasks) and len(callables) == 0:
            completed_tasks, running_tasks = await asyncio.wait(
                running_tasks, return_when=asyncio.FIRST_COMPLETED)
            raise_task_exceptions(completed_tasks)
            for completed_task in completed_tasks:
                completed_coro_function = completed_task.aio_coroutine_function
                now_ready = queue.completed(completed_coro_function)
                logger.debug("now_ready=%s", now_ready)
                new_callables, new_tasks = prepare_ready_set(now_ready)
                callables |= new_callables
                logger.debug("callables=%s", callables)
                running_tasks |= new_tasks
                logger.debug("running_tasks=%s", running_tasks)

    assert len(running_tasks) == 0
    assert queue.empty()

    logger.debug("exit, graph.name=%s", graph.name)
Example #6
0
def test_topological_queue_bug():
    graph = basic.DependencyGraph()
    graph.add_node("A")
    graph.add_node("B")
    queue = basic.TopologicalQueue(graph)
    assert queue.ready_set() == {"A", "B"}
Example #7
0
def test_topological_queue_cycle():
    with pytest.raises(basic.CircularDependency) as e:
        queue = basic.TopologicalQueue(
            basic.DependencyGraph(initial_dependencies={"A": {"A"}}))
    assert str(e.value) == "Circular dependency detected in graph"
Example #8
0
def test_topological_queue_singleton():
    queue = basic.TopologicalQueue(
        basic.DependencyGraph(initial_dependencies={"A": {}}))
    assert not queue.empty()
    assert queue.ready_set() == {"A"}
Example #9
0
def test_topological_queue_empty():
    queue = basic.TopologicalQueue(
        basic.DependencyGraph(initial_dependencies={}))
    assert queue.empty()