Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/sciline/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,12 @@ def get(
raise CycleError from e

dependents = _count_dependents(dependencies)
requested = set(keys)
results: dict[Hashable, Any] = {}
with reporter.run_computation(graph.values()):
for t in tasks:
results[t] = reporter.call_provider_with_reporting(graph[t], results)
_consume_arguments(graph[t], dependents, results)
_consume_arguments(graph[t], dependents, results, requested)

return tuple(results[key] for key in keys)

Expand All @@ -81,11 +82,19 @@ def _count_dependents(dependencies: dict[type, tuple[type, ...]]) -> Counter[typ


def _consume_arguments(
provider: Provider, counts: Counter[type], results: dict[Hashable, object]
provider: Provider,
counts: Counter[type],
results: dict[Hashable, object],
requested: set[Hashable],
) -> None:
"""Discard results that no remaining provider needs.

Requested keys are kept: they are returned to the caller, so their consumer
count reaching zero does not mean they are no longer needed.
"""
for arg in provider.arg_spec.keys():
counts[arg] -= 1
if counts[arg] == 0:
if counts[arg] == 0 and arg not in requested:
del results[arg]


Expand Down
14 changes: 14 additions & 0 deletions tests/pipeline_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,20 @@ def test_compute_with_NaiveScheduler() -> None:
assert res == 1.5


def test_compute_returns_requested_key_that_another_requested_key_depends_on(
scheduler: sl.scheduler.Scheduler,
) -> None:
def make_int_local() -> int:
return 3

def int_to_float_local(x: int) -> float:
return 0.5 * x

pipeline = sl.Pipeline([int_to_float_local, make_int_local])
# int is both a requested key and an argument of the provider of float.
assert pipeline.compute((int, float), scheduler=scheduler) == {int: 3, float: 1.5}


def test_bind_and_call_no_function() -> None:
pipeline = sl.Pipeline([make_int])
assert pipeline.bind_and_call(()) == ()
Expand Down
Loading