From 8f73c7784ab3b47ef6f0c30d3f1177a6a1d35559 Mon Sep 17 00:00:00 2001 From: Nat Noordanus Date: Wed, 27 Sep 2023 20:20:37 +0200 Subject: [PATCH] Make task dependecies work as expected for referenced tasks #168 --- poethepoet/task/ref.py | 33 ++++++++++++++++++++ tests/fixtures/graphs_project/pyproject.toml | 21 +++++++++++++ tests/test_graph_execution.py | 12 +++++++ 3 files changed, 66 insertions(+) diff --git a/poethepoet/task/ref.py b/poethepoet/task/ref.py index fd44a4e2b..ae3a1954c 100644 --- a/poethepoet/task/ref.py +++ b/poethepoet/task/ref.py @@ -32,8 +32,41 @@ def _handle_run( invocation = tuple(shlex.split(env.fill_template(self.content.strip()))) extra_args = [*invocation[1:], *extra_args] task = self.from_config(invocation[0], self._config, self._ui, invocation) + + if task.has_deps(): + return self._run_task_graph(task, context, extra_args, env) + return task.run(context=context, extra_args=extra_args, parent_env=env) + def _run_task_graph( + self, + task: "PoeTask", + context: "RunContext", + extra_args: Sequence[str], + env: "EnvVarsManager", + ) -> int: + from ..exceptions import ExecutionError + from .graph import TaskExecutionGraph + + graph = TaskExecutionGraph(task, context) + plan = graph.get_execution_plan() + for stage in plan: + for stage_task in stage: + if stage_task == task: + # The final sink task gets special treatment + return task.run( + context=context, extra_args=extra_args, parent_env=env + ) + + task_result = stage_task.run( + context=context, extra_args=stage_task.invocation[1:] + ) + if task_result: + raise ExecutionError( + f"Task graph aborted after failed task {stage_task.name!r}" + ) + return 0 + @classmethod def _validate_task_def( cls, task_name: str, task_def: Dict[str, Any], config: "PoeConfig" diff --git a/tests/fixtures/graphs_project/pyproject.toml b/tests/fixtures/graphs_project/pyproject.toml index 653e1d5e0..66f52ea70 100644 --- a/tests/fixtures/graphs_project/pyproject.toml +++ b/tests/fixtures/graphs_project/pyproject.toml @@ -18,3 +18,24 @@ _do_setup = "poe_test_echo here\nwe go...\n" deps = ["_do_setup", "think $subject1 $subject2"] uses = { greeting1 = "greet $subject1", greeting2 = "greet $subject2"} args = ["subject1", "subject2"] + + [tool.poe.tasks._a1] + help = "Dependency 1 of task a" + cmd = "echo A1" + + [tool.poe.tasks._a2] + help = "Dependency 2 of task a" + cmd = "echo A2" + + [tool.poe.tasks.a] + help = "Task a" + expr = "'a1: ' + ${a1} + ', a2: ' + ${a2}" + uses = {a1 = "_a1", a2 = "_a2"} + + [tool.poe.tasks.b] + help = "Task b" + cmd = "echo b" + + [tool.poe.tasks.ab] + help = "Sequence of tasks a and b" + sequence = ["a", "b"] diff --git a/tests/test_graph_execution.py b/tests/test_graph_execution.py index 0e7d37c81..01e0936b8 100644 --- a/tests/test_graph_execution.py +++ b/tests/test_graph_execution.py @@ -27,3 +27,15 @@ def test_uses_dry_run(run_poe_subproc): ) assert result.stdout == "" assert result.stderr == "" + + +def test_task_graph_in_sequence(run_poe_subproc): + result = run_poe_subproc("ab", project="graphs") + assert result.capture == ( + "Poe <= echo A1\n" + "Poe <= echo A2\n" + "Poe => 'a1: ' + ${a1} + ', a2: ' + ${a2}\n" + "Poe => echo b\n" + ) + assert result.stdout == ("a1: A1, a2: A2\nb\n") + assert result.stderr == ""