Skip to content

Commit 92160f6

Browse files
suecharomr-c
andcommitted
Factory: also parse command-line options
Co-authored-by: Michael R. Crusoe <[email protected]>
1 parent 8dee8e9 commit 92160f6

File tree

3 files changed

+75
-16
lines changed

3 files changed

+75
-16
lines changed

cwltool/factory.py

+72-13
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1+
"""Wrap a CWL document as a callable Python object."""
2+
3+
import argparse
4+
import functools
15
import os
6+
import sys
27
from typing import Any, Optional, Union
38

49
from . import load_tool
5-
from .context import LoadingContext, RuntimeContext
10+
from .argparser import arg_parser
11+
from .context import LoadingContext, RuntimeContext, getdefault
612
from .errors import WorkflowException
713
from .executors import JobExecutor, SingleJobExecutor
14+
from .main import find_default_container
815
from .process import Process
9-
from .utils import CWLObjectType
16+
from .resolver import tool_resolver
17+
from .secrets import SecretStore
18+
from .utils import DEFAULT_TMP_PREFIX, CWLObjectType
1019

1120

1221
class WorkflowStatus(Exception):
@@ -25,11 +34,13 @@ def __init__(self, t: Process, factory: "Factory") -> None:
2534
self.t = t
2635
self.factory = factory
2736

28-
def __call__(self, **kwargs):
29-
# type: (**Any) -> Union[str, Optional[CWLObjectType]]
30-
runtime_context = self.factory.runtime_context.copy()
31-
runtime_context.basedir = os.getcwd()
32-
out, status = self.factory.executor(self.t, kwargs, runtime_context)
37+
def __call__(self, **kwargs: Any) -> Union[str, Optional[CWLObjectType]]:
38+
"""
39+
Execute the process.
40+
41+
:raise WorkflowStatus: If the result is not a success.
42+
"""
43+
out, status = self.factory.executor(self.t, kwargs, self.factory.runtime_context)
3344
if status != "success":
3445
raise WorkflowStatus(out, status)
3546
else:
@@ -44,21 +55,27 @@ class Factory:
4455

4556
def __init__(
4657
self,
58+
argsl: Optional[list[str]] = None,
59+
args: Optional[argparse.Namespace] = None,
4760
executor: Optional[JobExecutor] = None,
4861
loading_context: Optional[LoadingContext] = None,
4962
runtime_context: Optional[RuntimeContext] = None,
5063
) -> None:
64+
"""Create a CWL Process factory from a CWL document."""
65+
if argsl is not None:
66+
args = arg_parser().parse_args(argsl)
5167
if executor is None:
52-
executor = SingleJobExecutor()
53-
self.executor = executor
68+
self.executor: JobExecutor = SingleJobExecutor()
69+
else:
70+
self.executor = executor
5471
if runtime_context is None:
55-
self.runtime_context = RuntimeContext()
72+
self.runtime_context = RuntimeContext(vars(args))
73+
self._fix_runtime_context()
5674
else:
5775
self.runtime_context = runtime_context
5876
if loading_context is None:
59-
self.loading_context = LoadingContext()
60-
self.loading_context.singularity = self.runtime_context.singularity
61-
self.loading_context.podman = self.runtime_context.podman
77+
self.loading_context = LoadingContext(vars(args))
78+
self._fix_loading_context(self.runtime_context)
6279
else:
6380
self.loading_context = loading_context
6481

@@ -68,3 +85,45 @@ def make(self, cwl: Union[str, dict[str, Any]]) -> Callable:
6885
if isinstance(load, int):
6986
raise WorkflowException("Error loading tool")
7087
return Callable(load, self)
88+
89+
def _fix_loading_context(self, runtime_context: RuntimeContext) -> None:
90+
self.loading_context.resolver = getdefault(self.loading_context.resolver, tool_resolver)
91+
self.loading_context.singularity = runtime_context.singularity
92+
self.loading_context.podman = runtime_context.podman
93+
94+
def _fix_runtime_context(self) -> None:
95+
self.runtime_context.basedir = os.getcwd()
96+
self.runtime_context.find_default_container = functools.partial(
97+
find_default_container, default_container=None, use_biocontainers=None
98+
)
99+
100+
if sys.platform == "darwin":
101+
default_mac_path = "/private/tmp/docker_tmp"
102+
if self.runtimeContext.tmp_outdir_prefix == DEFAULT_TMP_PREFIX:
103+
self.runtimeContext.tmp_outdir_prefix = default_mac_path
104+
105+
for dirprefix in ("tmpdir_prefix", "tmp_outdir_prefix", "cachedir"):
106+
if (
107+
getattr(self.runtime_context, dirprefix)
108+
and getattr(self.runtime_context, dirprefix) != DEFAULT_TMP_PREFIX
109+
):
110+
sl = (
111+
"/"
112+
if getattr(self.runtime_context, dirprefix).endswith("/")
113+
or dirprefix == "cachedir"
114+
else ""
115+
)
116+
setattr(
117+
self.runtime_context,
118+
dirprefix,
119+
os.path.abspath(getattr(self.runtime_context, dirprefix)) + sl,
120+
)
121+
if not os.path.exists(os.path.dirname(getattr(self.runtime_context, dirprefix))):
122+
try:
123+
os.makedirs(os.path.dirname(getattr(self.runtime_context, dirprefix)))
124+
except Exception as e:
125+
print("Failed to create directory: %s", e)
126+
127+
self.runtime_context.secret_store = getdefault(
128+
self.runtime_context.secret_store, SecretStore()
129+
)

tests/test_context.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def test_replace_default_stdout_stderr() -> None:
2020
runtime_context = RuntimeContext()
2121
runtime_context.default_stdout = subprocess.DEVNULL # type: ignore
2222
runtime_context.default_stderr = subprocess.DEVNULL # type: ignore
23-
factory = Factory(None, None, runtime_context)
23+
factory = Factory(runtime_context=runtime_context)
2424
echo = factory.make(get_data("tests/echo.cwl"))
2525

2626
assert echo(inp="foo") == {"out": "foo\n"}

tests/test_parallel.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def test_sequential_workflow(tmp_path: Path) -> None:
1515
runtime_context = RuntimeContext()
1616
runtime_context.outdir = str(tmp_path)
1717
runtime_context.select_resources = executor.select_resources
18-
factory = Factory(executor, None, runtime_context)
18+
factory = Factory(executor=executor, runtime_context=runtime_context)
1919
echo = factory.make(get_data(test_file))
2020
file_contents = {"class": "File", "location": get_data("tests/wf/whale.txt")}
2121
assert echo(file1=file_contents) == {"count_output": 16}
@@ -25,7 +25,7 @@ def test_sequential_workflow(tmp_path: Path) -> None:
2525
def test_scattered_workflow() -> None:
2626
test_file = "tests/wf/scatter-wf4.cwl"
2727
job_file = "tests/wf/scatter-job2.json"
28-
factory = Factory(MultithreadedJobExecutor())
28+
factory = Factory(executor=MultithreadedJobExecutor())
2929
echo = factory.make(get_data(test_file))
3030
with open(get_data(job_file)) as job:
3131
assert echo(**json.load(job)) == {"out": ["foo one three", "foo two four"]}

0 commit comments

Comments
 (0)