Skip to content

Commit 56e4657

Browse files
committed
moving bindings from Input spec to task
1 parent 363081d commit 56e4657

File tree

3 files changed

+44
-62
lines changed

3 files changed

+44
-62
lines changed

pydra/engine/specs.py

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,15 @@ def check_fields_input_spec(self):
187187
or "pydra.engine.specs.File" in str(fld.type)
188188
or "pydra.engine.specs.Directory" in str(fld.type)
189189
):
190-
self._file_check_n_bindings(fld)
190+
self._file_check(fld)
191191

192192
for nm, required in require_to_check.items():
193193
required_notfound = [el for el in required if el not in names]
194194
if required_notfound:
195195
raise AttributeError(f"{nm} requires {required_notfound}")
196196

197-
def _file_check_n_bindings(self, field):
198-
"""for tasks without container, this is simple check if the file exists"""
197+
def _file_check(self, field):
198+
"""checking if the file exists"""
199199
if isinstance(getattr(self, field.name), list):
200200
# if value is a list and type is a list of Files/Directory, checking all elements
201201
if field.type in [ty.List[File], ty.List[Directory]]:
@@ -682,39 +682,6 @@ class ContainerSpec(ShellSpec):
682682
container_xargs: ty.Optional[ty.List[str]] = attr.ib(
683683
default=None, metadata={"help_string": "todo"}
684684
)
685-
"""Execution arguments to run the image."""
686-
bindings: ty.Optional[
687-
ty.List[
688-
ty.Tuple[
689-
Path, # local path
690-
Path, # container path
691-
ty.Optional[str], # mount mode
692-
]
693-
]
694-
] = attr.ib(default=None, metadata={"help_string": "bindings"})
695-
"""Mount points to be bound into the container."""
696-
697-
def _file_check_n_bindings(self, field):
698-
if field.name == "image":
699-
return
700-
file = Path(getattr(self, field.name))
701-
if field.metadata.get("container_path"):
702-
# if the path is in a container the input should be treated as a str (hash as a str)
703-
# field.type = "str"
704-
# setattr(self, field.name, str(file))
705-
pass
706-
# if this is a local path, checking if the path exists
707-
elif file.exists():
708-
if self.bindings is None:
709-
self.bindings = []
710-
self.bindings.append((file.parent, f"/pydra_inp_{field.name}", "ro"))
711-
# error should be raised only if the type is strictly File or Directory
712-
elif field.type in [File, Directory]:
713-
raise FileNotFoundError(
714-
f"the file {file} from {field.name} input does not exist, "
715-
f"if the file comes from the container, "
716-
f"use field.metadata['container_path']=True"
717-
)
718685

719686

720687
@attr.s(auto_attribs=True, kw_only=True)

pydra/engine/task.py

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@
5656
DockerSpec,
5757
SingularitySpec,
5858
attr_fields,
59+
File,
60+
Directory,
5961
)
6062
from .helpers import (
6163
ensure_list,
@@ -568,6 +570,7 @@ def __init__(
568570
if input_spec is None:
569571
input_spec = SpecInfo(name="Inputs", fields=[], bases=(ContainerSpec,))
570572
self.output_cpath = Path(output_cpath)
573+
self.bindings = {}
571574
super().__init__(
572575
name=name,
573576
input_spec=input_spec,
@@ -615,33 +618,12 @@ def bind_paths(self):
615618
mount points: dict
616619
mapping from local path to tuple of container path + mode
617620
"""
618-
bind_paths = {}
619-
output_dir_cpath = None
620-
if self.inputs.bindings is None:
621-
self.inputs.bindings = []
621+
self._check_inputs()
622622
output_dir = self.output_dir
623-
# This part has to stay for now!!!
624-
# I'm creating self.inputs.bindings based on the input in TaskBase._run
625-
# in self.inputs.check_fields_input_spec() (see specs.py)
626-
for binding in self.inputs.bindings:
627-
binding = list(binding)
628-
if len(binding) == 3:
629-
lpath, cpath, mode = binding
630-
elif len(binding) == 2:
631-
lpath, cpath, mode = binding + ["rw"]
632-
else:
633-
raise Exception(
634-
f"binding should have length 2, 3, or 4, it has {len(binding)}"
635-
)
636-
if Path(lpath) == output_dir:
637-
output_dir_cpath = cpath
638-
if mode is None:
639-
mode = "rw" # default
640-
bind_paths[Path(lpath)] = (Path(cpath), mode)
641-
# output_dir is added to the bindings if not part of self.inputs.bindings
642-
if not output_dir_cpath:
643-
bind_paths[output_dir] = (self.output_cpath, "rw")
644-
return bind_paths
623+
# TODO: output dir should be always "rw"
624+
if output_dir not in self.bindings:
625+
self.bindings[output_dir] = (self.output_cpath, "rw")
626+
return self.bindings
645627

646628
def binds(self, opt):
647629
"""
@@ -655,6 +637,38 @@ def binds(self, opt):
655637
bargs.extend([opt, f"{lpath}:{cpath}:{mode}"])
656638
return bargs
657639

640+
def _check_inputs(self):
641+
fields = attr_fields(self.inputs)
642+
for fld in fields:
643+
if (
644+
fld.type in [File, Directory]
645+
or "pydra.engine.specs.File" in str(fld.type)
646+
or "pydra.engine.specs.Directory" in str(fld.type)
647+
):
648+
649+
if fld.name == "image":
650+
continue
651+
file = Path(getattr(self.inputs, fld.name))
652+
if fld.metadata.get("container_path"):
653+
# if the path is in a container the input should be treated as a str (hash as a str)
654+
# field.type = "str"
655+
# setattr(self, field.name, str(file))
656+
pass
657+
# if this is a local path, checking if the path exists
658+
# TODO: if copyfile, ro -> rw
659+
elif file.exists(): # is it ok if two inputs have the same parent?
660+
self.bindings[Path(file.parent)] = (
661+
Path(f"/pydra_inp_{fld.name}"),
662+
"ro",
663+
)
664+
# error should be raised only if the type is strictly File or Directory
665+
elif fld.type in [File, Directory]:
666+
raise FileNotFoundError(
667+
f"the file {file} from {fld.name} input does not exist, "
668+
f"if the file comes from the container, "
669+
f"use field.metadata['container_path']=True"
670+
)
671+
658672

659673
class DockerTask(ContainerTask):
660674
"""Extend shell command task for containerized execution with the Docker Engine."""

pydra/engine/tests/test_dockertask.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,7 @@ def test_docker_inputspec_3(plugin, tmpdir):
10611061

10621062
@no_win
10631063
@need_docker
1064+
@pytest.mark.skip(reason="we probably don't want to support container_path")
10641065
def test_docker_inputspec_3a(plugin, tmpdir):
10651066
"""input file does not exist in the local file system,
10661067
but metadata["container_path"] is not used,

0 commit comments

Comments
 (0)