Skip to content

Commit b0a6b5a

Browse files
authored
Correctly handle file and directory literals (#218)
* Correctly handle file and directory literals produced by expression tool in output. * Fix sandboxjs to use "docker images" before "docker pull" so it doesn't rely on being online to use node:slim for JS evaluation.
1 parent 5c8ee81 commit b0a6b5a

File tree

5 files changed

+35
-26
lines changed

5 files changed

+35
-26
lines changed

cwltool/draft2tool.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import shellescape
1717
from typing import Any, Callable, cast, Generator, Text, Union
1818

19-
from .process import Process, shortname, uniquename, getListing, normalizeFilesDirs
19+
from .process import Process, shortname, uniquename, getListing, normalizeFilesDirs, compute_checksums
2020
from .errors import WorkflowException
2121
from .utils import aslist
2222
from . import expression
@@ -146,19 +146,6 @@ def check_adjust(builder, f):
146146
raise WorkflowException("Invalid filename: '%s' contains illegal characters" % (f["basename"]))
147147
return f
148148

149-
def compute_checksums(fs_access, fileobj):
150-
if "checksum" not in fileobj:
151-
checksum = hashlib.sha1()
152-
with fs_access.open(fileobj["location"], "rb") as f:
153-
contents = f.read(1024*1024)
154-
while contents != "":
155-
checksum.update(contents)
156-
contents = f.read(1024*1024)
157-
f.seek(0, 2)
158-
filesize = f.tell()
159-
fileobj["checksum"] = "sha1$%s" % checksum.hexdigest()
160-
fileobj["size"] = filesize
161-
162149
class CommandLineTool(Process):
163150
def __init__(self, toolpath_object, **kwargs):
164151
# type: (Dict[Text, Any], **Any) -> None

cwltool/load_tool.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ def validate_document(document_loader, workflowobj, uri,
105105
fileuri = urlparse.urldefrag(uri)[0]
106106

107107
if "cwlVersion" in workflowobj:
108+
if not isinstance(workflowobj["cwlVersion"], (str, Text)):
109+
raise Exception("'cwlVersion' must be a string, got %s" % type(workflowobj["cwlVersion"]))
108110
workflowobj["cwlVersion"] = re.sub(
109111
r"^(?:cwl:|https://w3id.org/cwl/cwl#)", "",
110112
workflowobj["cwlVersion"])

cwltool/pathmapper.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,21 +145,21 @@ def visitlisting(self, listing, stagedir, basedir):
145145
for ld in listing:
146146
tgt = os.path.join(stagedir, ld["basename"])
147147
if ld["class"] == "Directory":
148-
self.visit(ld, tgt, basedir, copy=ld.get("writable", False))
148+
self.visit(ld, stagedir, basedir, copy=ld.get("writable", False))
149149
else:
150150
self.visit(ld, stagedir, basedir, copy=ld.get("writable", False))
151151

152152
def visit(self, obj, stagedir, basedir, copy=False):
153153
# type: (Dict[Text, Any], Text, Text, bool) -> None
154+
tgt = os.path.join(stagedir, obj["basename"])
154155
if obj["class"] == "Directory":
155-
self._pathmap[obj["location"]] = MapperEnt(obj["location"], stagedir, "Directory")
156-
self.visitlisting(obj.get("listing", []), stagedir, basedir)
156+
self._pathmap[obj["location"]] = MapperEnt(obj["location"], tgt, "Directory")
157+
self.visitlisting(obj.get("listing", []), tgt, basedir)
157158
elif obj["class"] == "File":
158159
path = obj["location"]
159160
if path in self._pathmap:
160161
return
161162
ab = abspath(path, basedir)
162-
tgt = os.path.join(stagedir, obj["basename"])
163163
if "contents" in obj and obj["location"].startswith("_:"):
164164
self._pathmap[obj["location"]] = MapperEnt(obj["contents"], tgt, "CreateFile")
165165
else:

cwltool/process.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import errno
1313
import shutil
1414
import uuid
15+
import hashlib
1516

1617
import abc
1718
import schema_salad.validate as validate
@@ -200,14 +201,14 @@ def relocateOutputs(outputObj, outdir, output_dirs, action):
200201
return outputObj
201202

202203
def moveIt(src, dst):
203-
for a in output_dirs:
204-
if src.startswith(a):
205-
if action == "move":
204+
if action == "move":
205+
for a in output_dirs:
206+
if src.startswith(a):
206207
_logger.debug("Moving %s to %s", src, dst)
207208
shutil.move(src, dst)
208-
elif action == "copy":
209-
_logger.debug("Copying %s to %s", src, dst)
210-
shutil.copy(src, dst)
209+
return
210+
_logger.debug("Copying %s to %s", src, dst)
211+
shutil.copy(src, dst)
211212

212213
outfiles = [] # type: List[Dict[Text, Any]]
213214
collectFilesAndDirs(outputObj, outfiles)
@@ -216,6 +217,10 @@ def moveIt(src, dst):
216217

217218
def _check_adjust(f):
218219
f["location"] = "file://" + pm.mapper(f["location"])[1]
220+
if "contents" in f:
221+
del f["contents"]
222+
if f["class"] == "File":
223+
compute_checksums(StdFsAccess(""), f)
219224
return f
220225

221226
adjustFileObjs(outputObj, _check_adjust)
@@ -700,3 +705,16 @@ def scandeps(base, doc, reffields, urlfields, loadref):
700705
normalizeFilesDirs(r)
701706
r = mergedirs(r)
702707
return r
708+
709+
def compute_checksums(fs_access, fileobj):
710+
if "checksum" not in fileobj:
711+
checksum = hashlib.sha1()
712+
with fs_access.open(fileobj["location"], "rb") as f:
713+
contents = f.read(1024*1024)
714+
while contents != "":
715+
checksum.update(contents)
716+
contents = f.read(1024*1024)
717+
f.seek(0, 2)
718+
filesize = f.tell()
719+
fileobj["checksum"] = "sha1$%s" % checksum.hexdigest()
720+
fileobj["size"] = filesize

cwltool/sandboxjs.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ def new_js_proc():
4545
nodeimg = "node:slim"
4646
global have_node_slim
4747
if not have_node_slim:
48-
nodejsimg = subprocess.check_output(["docker", "pull", nodeimg])
49-
_logger.info("Pulled Docker image %s %s", nodeimg, nodejsimg)
48+
dockerimgs = subprocess.check_output(["docker", "images", nodeimg])
49+
if len(dockerimgs.split("\n")) <= 1:
50+
nodejsimg = subprocess.check_output(["docker", "pull", nodeimg])
51+
_logger.info("Pulled Docker image %s %s", nodeimg, nodejsimg)
5052
have_node_slim = True
5153
nodejs = subprocess.Popen(["docker", "run",
5254
"--attach=STDIN", "--attach=STDOUT", "--attach=STDERR",

0 commit comments

Comments
 (0)