Skip to content

Commit 346f421

Browse files
authored
Step name callback (#2109)
1 parent f94719e commit 346f421

File tree

4 files changed

+75
-3
lines changed

4 files changed

+75
-3
lines changed

build-cwltool-docker.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ ${engine} run -t -v /var/run/docker.sock:/var/run/docker.sock \
88
-v /tmp:/tmp \
99
-v "$PWD":/tmp/cwltool \
1010
quay.io/commonwl/cwltool_module /bin/sh -c \
11-
"apk add gcc bash git && pip install -r/tmp/cwltool/test-requirements.txt ; pytest -k 'not (test_bioconda or test_double_overwrite or test_env_filtering or test_biocontainers or test_disable_file_overwrite_without_ext or test_disable_file_creation_in_outdir_with_ext or test_write_write_conflict or test_directory_literal_with_real_inputs_inside or test_revsort_workflow or test_stdin_with_id_preset or test_no_compute_chcksum or test_packed_workflow_execution[tests/wf/count-lines1-wf.cwl-tests/wf/wc-job.json-False] or test_sequential_workflow or test_single_process_subwf_subwf_inline_step or test_cache_dockerreq_hint_instead_of_req)' --ignore-glob '*test_udocker.py' -n 0 -v -rs --pyargs cwltool"
11+
"apk add gcc bash git && pip install -r/tmp/cwltool/test-requirements.txt ; pytest -k 'not (test_bioconda or test_double_overwrite or test_env_filtering or test_biocontainers or test_disable_file_overwrite_without_ext or test_disable_file_creation_in_outdir_with_ext or test_write_write_conflict or test_directory_literal_with_real_inputs_inside or test_revsort_workflow or test_stdin_with_id_preset or test_no_compute_chcksum or test_packed_workflow_execution[tests/wf/count-lines1-wf.cwl-tests/wf/wc-job.json-False] or test_sequential_workflow or test_single_process_subwf_subwf_inline_step or test_cache_dockerreq_hint_instead_of_req or test_workflow_job_step_name_callback)' --ignore-glob '*test_udocker.py' -n 0 -v -rs --pyargs cwltool"

cwltool/context.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from .process import Process
3030
from .secrets import SecretStore
3131
from .software_requirements import DependenciesConfiguration
32+
from .workflow_job import WorkflowJobStep
3233

3334

3435
class ContextBase:
@@ -191,6 +192,10 @@ def __init__(self, kwargs: Optional[dict[str, Any]] = None) -> None:
191192
self.default_stderr: Optional[Union[IO[bytes], TextIO]] = None
192193
self.validate_only: bool = False
193194
self.validate_stdout: Optional["SupportsWrite[str]"] = None
195+
self.workflow_job_step_name_callback: Optional[
196+
Callable[[WorkflowJobStep, CWLObjectType], str]
197+
] = None
198+
194199
super().__init__(kwargs)
195200
if self.tmp_outdir_prefix == "":
196201
self.tmp_outdir_prefix = self.tmpdir_prefix

cwltool/workflow_job.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ def job(
6060
) -> JobsGeneratorType:
6161
runtimeContext = runtimeContext.copy()
6262
runtimeContext.part_of = self.name
63-
runtimeContext.name = shortname(self.id)
63+
64+
if runtimeContext.workflow_job_step_name_callback is not None:
65+
vfinputs = {shortname(k): v for k, v in joborder.items()}
66+
runtimeContext.name = runtimeContext.workflow_job_step_name_callback(self, vfinputs)
67+
else:
68+
runtimeContext.name = shortname(self.id)
6469

6570
_logger.info("[%s] start", self.name)
6671

tests/test_context.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import subprocess
22
import sys
3+
import logging
4+
from io import StringIO
5+
from typing import MutableMapping, cast
36

47
from cwltool.context import RuntimeContext
58
from cwltool.factory import Factory
9+
from cwltool.utils import CWLObjectType
10+
from cwltool.workflow_job import WorkflowJobStep
11+
from pathlib import Path
612

7-
from .util import get_data
13+
from .util import get_data, needs_docker
814

915

1016
def test_replace_default_stdout_stderr() -> None:
@@ -26,3 +32,59 @@ def test_replace_default_stdout_stderr() -> None:
2632
assert echo(inp="foo") == {"out": "foo\n"}
2733
sys.stdout = original_stdout
2834
sys.stderr = original_stderr
35+
36+
37+
@needs_docker
38+
def test_workflow_job_step_name_callback() -> None:
39+
"""Test ability to hook custom workflow step naming"""
40+
41+
stream = StringIO()
42+
streamhandler = logging.StreamHandler(stream)
43+
_logger = logging.getLogger("cwltool")
44+
_logger.addHandler(streamhandler)
45+
46+
try:
47+
runtime_context = RuntimeContext()
48+
49+
def step_name_hook(step: WorkflowJobStep, job: CWLObjectType) -> str:
50+
j1 = cast(MutableMapping[str, CWLObjectType], job)
51+
inp = cast(MutableMapping[str, str], j1.get("revtool_input", j1.get("sorted_input")))
52+
return "%s on %s" % (
53+
step.name,
54+
inp.get("basename"),
55+
)
56+
57+
runtime_context.workflow_job_step_name_callback = step_name_hook
58+
59+
factory = Factory(None, None, runtime_context)
60+
revsort = factory.make(get_data("tests/wf/revsort.cwl"))
61+
62+
result = revsort(
63+
workflow_input={
64+
"class": "File",
65+
"location": Path(get_data("tests/wf/whale.txt")).as_uri(),
66+
"format": "https://www.iana.org/assignments/media-types/text/plain",
67+
}
68+
)
69+
70+
result = cast(CWLObjectType, result)
71+
72+
sorted_out = cast(MutableMapping[str, str], result["sorted_output"])
73+
loc = sorted_out["location"]
74+
75+
assert result == {
76+
"sorted_output": {
77+
"basename": "output.txt",
78+
"checksum": "sha1$b9214658cc453331b62c2282b772a5c063dbd284",
79+
"class": "File",
80+
"http://commonwl.org/cwltool#generation": 0,
81+
"nameext": ".txt",
82+
"nameroot": "output",
83+
"size": 1111,
84+
"location": loc,
85+
},
86+
}
87+
88+
assert "rev on whale.txt" in stream.getvalue()
89+
finally:
90+
_logger.removeHandler(streamhandler)

0 commit comments

Comments
 (0)