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
6 changes: 5 additions & 1 deletion pydra/engine/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,16 @@ def copyfile_workflow(
) -> workflow.Outputs:
"""if file in the wf results, the file will be copied to the workflow directory"""

clashes_to_avoid: set[Path] = set()
for field in attrs_fields(outputs):
value = getattr(outputs, field.name)
# if the field is a path or it can contain a path _copyfile_single_value is run
# to move all files and directories to the workflow directory
new_value = copy_nested_files(
value, wf_path, mode=FileSet.CopyMode.hardlink_or_copy
value,
wf_path,
mode=FileSet.CopyMode.hardlink_or_copy,
clashes_to_avoid=clashes_to_avoid,
)
setattr(outputs, field.name, new_value)
return outputs
Expand Down
35 changes: 33 additions & 2 deletions pydra/engine/tests/test_result.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
from pydra.engine.result import Result, Runtime
from pathlib import Path
from fileformats.text import TextFile
from pydra.compose import python
from pydra.engine.result import Result, Runtime, copyfile_workflow


@python.define(outputs=["d", "e", "f"])
def MockTask(
a: TextFile, b: TextFile, c: TextFile
) -> tuple[TextFile, TextFile, TextFile]:
return a, b, c


def test_runtime():
Expand All @@ -8,9 +18,30 @@ def test_runtime():
assert hasattr(runtime, "cpu_peak_percent")


def test_result(tmp_path):
def test_result(tmp_path: Path):
result = Result(cache_dir=tmp_path)
assert hasattr(result, "runtime")
assert hasattr(result, "outputs")
assert hasattr(result, "errored")
assert getattr(result, "errored") is False


def test_copyfile_workflow_conflicting_filenames(tmp_path: Path) -> None:
"""Copy outputs to the workflow output directory with conflicting filenames.
The filenames should be disambiguated to avoid clashes"""
file1 = TextFile.sample(stem="out")
file2 = TextFile.sample(stem="out")
file3 = TextFile.sample(stem="out")

workflow_dir = tmp_path / "output"
mock = MockTask(a=file1, b=file2, c=file3)
outputs = mock()
workflow_dir.mkdir()

copyfile_workflow(workflow_dir, outputs)

assert sorted(p.stem for p in workflow_dir.iterdir()) == [
"out",
"out (1)",
"out (2)",
]
4 changes: 3 additions & 1 deletion pydra/utils/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,7 @@ def copy_nested_files(
value: ty.Any,
dest_dir: os.PathLike,
supported_modes: generic.FileSet.CopyMode = generic.FileSet.CopyMode.any,
clashes_to_avoid: set[Path] | None = None,
**kwargs,
) -> ty.Any:
"""Copies all "file-sets" found within the nested value (e.g. dict, list,...) into the
Expand All @@ -1229,7 +1230,8 @@ def copy_nested_files(

# Set to keep track of file paths that have already been copied
# to allow FileSet.copy to avoid name clashes
clashes_to_avoid = set()
if clashes_to_avoid is None:
clashes_to_avoid = set()

def copy_fileset(fileset: generic.FileSet):
try:
Expand Down
Loading