Skip to content

Commit be7c7cd

Browse files
committed
propagate writable attribute to secondaryfiles
Fixes: #2131
1 parent dbcec2a commit be7c7cd

File tree

5 files changed

+70
-9
lines changed

5 files changed

+70
-9
lines changed

cwltool/command_line_tool.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -611,10 +611,16 @@ def _initialworkdir(self, j: Optional[JobBase], builder: Builder) -> None:
611611
continue
612612

613613
et: CWLObjectType = {}
614+
writable = t.get("writable", False)
615+
et["writable"] = writable
614616
if isinstance(entry, Mapping) and entry.get("class") in (
615617
"File",
616618
"Directory",
617619
):
620+
if writable and "secondaryFiles" in entry:
621+
secFiles = cast(MutableSequence[CWLObjectType], entry["secondaryFiles"])
622+
for sf in secFiles:
623+
sf["writable"] = writable
618624
et["entry"] = cast(CWLOutputType, entry)
619625
else:
620626
if isinstance(entry, str):
@@ -650,7 +656,6 @@ def _initialworkdir(self, j: Optional[JobBase], builder: Builder) -> None:
650656
et["entryname"] = entryname_field
651657
else:
652658
et["entryname"] = None
653-
et["writable"] = t.get("writable", False)
654659
ls.append(et)
655660
else:
656661
# Expression, must return a Dirent, File, Directory
@@ -700,13 +705,14 @@ def _initialworkdir(self, j: Optional[JobBase], builder: Builder) -> None:
700705
)
701706

702707
if t2.get("entryname") or t2.get("writable"):
703-
t2 = copy.deepcopy(t2)
704-
t2entry = cast(CWLObjectType, t2["entry"])
708+
t2copy = copy.deepcopy(t2)
709+
t2entry = cast(CWLObjectType, t2copy["entry"])
705710
if t2.get("entryname"):
706-
t2entry["basename"] = t2["entryname"]
707-
t2entry["writable"] = t2.get("writable")
711+
t2entry["basename"] = t2copy["entryname"]
712+
t2entry["writable"] = t2copy.get("writable")
713+
t2["entry"] = t2entry
708714

709-
ls[i] = cast(CWLObjectType, t2["entry"])
715+
ls[i] = t2["entry"]
710716

711717
for i, t3 in enumerate(ls):
712718
if t3.get("class") not in ("File", "Directory"):
@@ -753,14 +759,21 @@ def _initialworkdir(self, j: Optional[JobBase], builder: Builder) -> None:
753759
for entry in ls:
754760
if "basename" in entry:
755761
basename = cast(str, entry["basename"])
756-
entry["dirname"] = os.path.join(builder.outdir, os.path.dirname(basename))
762+
dirname = os.path.join(builder.outdir, os.path.dirname(basename))
763+
entry["dirname"] = dirname
757764
entry["basename"] = os.path.basename(basename)
765+
if "secondaryFiles" in entry:
766+
for sec_file in cast(
767+
MutableSequence[CWLObjectType], entry["secondaryFiles"]
768+
):
769+
sec_file["dirname"] = dirname
758770
normalizeFilesDirs(entry)
759771
self.updatePathmap(
760772
cast(Optional[str], entry.get("dirname")) or builder.outdir,
761773
cast(PathMapper, builder.pathmapper),
762774
entry,
763775
)
776+
764777
if "listing" in entry:
765778

766779
def remove_dirname(d: CWLObjectType) -> None:

cwltool/pathmapper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,13 @@ def visit(
111111
copy: bool = False,
112112
staged: bool = False,
113113
) -> None:
114+
if obj["location"] in self._pathmap:
115+
return
114116
stagedir = cast(Optional[str], obj.get("dirname")) or stagedir
115117
tgt = os.path.join(
116118
stagedir,
117119
cast(str, obj["basename"]),
118120
)
119-
if obj["location"] in self._pathmap:
120-
return
121121
if obj["class"] == "Directory":
122122
location = cast(str, obj["location"])
123123
if location.startswith("file://"):
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"example_file_with_secondary": {
3+
"class": "File",
4+
"location": "2.fasta",
5+
"secondaryFiles": [
6+
{
7+
"class": "File",
8+
"location": "2.fastq"
9+
}
10+
]
11+
}
12+
}

tests/iwdr_writable_secfile.cwl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
cwlVersion: v1.2
2+
class: CommandLineTool
3+
4+
requirements:
5+
InlineJavascriptRequirement: {}
6+
InitialWorkDirRequirement:
7+
listing:
8+
- entry: $(inputs.example_file_with_secondary)
9+
writable: true
10+
inputs:
11+
example_file_with_secondary:
12+
type: File
13+
secondaryFiles:
14+
- pattern: "^.fastq"
15+
required: true
16+
outputs:
17+
same_file:
18+
type: stdout
19+
20+
baseCommand: cat
21+
arguments:
22+
- $(inputs.example_file_with_secondary.path)
23+
- $(inputs.example_file_with_secondary.path.split('.')[0]+'.fastq')

tests/test_iwdr.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,16 @@ def test_iwdr_permutations_singularity_inplace(
376376
)
377377
== 0
378378
)
379+
380+
381+
def test_iwdr_writable_secondaryfiles(tmp_path: Path) -> None:
382+
"""Confirm that a writable primary file and its secondary files are still co-located."""
383+
err_code, _, _ = get_main_output(
384+
[
385+
"--outdir",
386+
str(tmp_path),
387+
get_data("tests/iwdr_writable_secfile.cwl"),
388+
get_data("tests/iwdr_writable_secfile-inputs.json"),
389+
]
390+
)
391+
assert err_code == 0

0 commit comments

Comments
 (0)