Skip to content

Commit 07ebbea

Browse files
authored
Merge pull request #1374 from common-workflow-language/tmpdir_prefix_fix
unify and fix tempdir creation logic
2 parents 98c3e76 + 43f27e3 commit 07ebbea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+710
-504
lines changed

Makefile

+6-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ MODULE=cwltool
2626
# `[[` conditional expressions.
2727
PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py
2828
DEVPKGS=diff_cover black pylint coverage pep257 pydocstyle flake8 mypy\
29-
pytest-xdist isort wheel -rtest-requirements.txt
29+
pytest-xdist isort wheel autoflake -rtest-requirements.txt
3030
DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \
3131
python-flake8 python-mock shellcheck
3232
VERSION=3.0.$(shell TZ=UTC git log --first-parent --max-count=1 \
@@ -84,6 +84,9 @@ clean: FORCE
8484
sort_imports:
8585
isort ${MODULE}/*.py tests/*.py setup.py
8686

87+
remove_unused_imports: $(PYSOURCES)
88+
autoflake --in-place --remove-all-unused-imports $^
89+
8790
pep257: pydocstyle
8891
## pydocstyle : check Python code style
8992
pydocstyle: $(PYSOURCES)
@@ -154,7 +157,7 @@ list-author-emails:
154157
@git log --format='%aN,%aE' | sort -u | grep -v 'root'
155158

156159
mypy3: mypy
157-
mypy: ${PYSOURCES}
160+
mypy: $(filter-out setup.py gittagger.py,${PYSOURCES})
158161
if ! test -f $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))')/py.typed ; \
159162
then \
160163
rm -Rf typeshed/2and3/ruamel/yaml ; \
@@ -163,7 +166,7 @@ mypy: ${PYSOURCES}
163166
fi # if minimally required ruamel.yaml version is 0.15.99 or greater, than the above can be removed
164167
MYPYPATH=$$MYPYPATH:typeshed/3:typeshed/2and3 mypy --disallow-untyped-calls \
165168
--warn-redundant-casts \
166-
cwltool
169+
$^
167170

168171
mypyc: ${PYSOURCES}
169172
MYPYPATH=typeshed/2and3/:typeshed/3 CWLTOOL_USE_MYPYC=1 pip install --verbose -e . && pytest --ignore cwltool/schemas --basetemp ./tmp

cwltool.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env python3
2+
# PYTHON_ARGCOMPLETE_OK
23
"""Convenience entry point for cwltool.
34
45
This can be used instead of the recommended method of `./setup.py install`

cwltool/argparser.py

+58-38
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,15 @@
2626

2727
def arg_parser() -> argparse.ArgumentParser:
2828
parser = argparse.ArgumentParser(
29-
description="Reference executor for Common Workflow Language standards."
29+
description="Reference executor for Common Workflow Language standards. "
30+
"Not for production use."
3031
)
3132
parser.add_argument("--basedir", type=str)
3233
parser.add_argument(
3334
"--outdir",
3435
type=str,
3536
default=os.path.abspath("."),
36-
help="Output directory, default current directory",
37+
help="Output directory. The default is the current directory.",
3738
)
3839

3940
parser.add_argument(
@@ -47,17 +48,18 @@ def arg_parser() -> argparse.ArgumentParser:
4748
"--preserve-environment",
4849
type=str,
4950
action="append",
50-
help="Preserve specific environment variable when "
51-
"running CommandLineTools. May be provided multiple "
52-
"times.",
51+
help="Preserve specific environment variable when running "
52+
"CommandLineTools without a software container. May be provided "
53+
"multiple times. The default is to preserve only the PATH.",
5354
metavar="ENVVAR",
5455
default=["PATH"],
5556
dest="preserve_environment",
5657
)
5758
envgroup.add_argument(
5859
"--preserve-entire-environment",
5960
action="store_true",
60-
help="Preserve all environment variable when running " "CommandLineTools.",
61+
help="Preserve all environment variables when running CommandLineTools "
62+
"without a software container.",
6163
default=False,
6264
dest="preserve_entire_environment",
6365
)
@@ -82,8 +84,8 @@ def arg_parser() -> argparse.ArgumentParser:
8284
cidgroup = parser.add_argument_group(
8385
"Options for recording the Docker container identifier into a file."
8486
)
85-
# Disabled as containerid is now saved by default
8687
cidgroup.add_argument(
88+
# Disabled as containerid is now saved by default
8789
"--record-container-id",
8890
action="store_true",
8991
default=False,
@@ -94,7 +96,7 @@ def arg_parser() -> argparse.ArgumentParser:
9496
cidgroup.add_argument(
9597
"--cidfile-dir",
9698
type=str,
97-
help="Store the Docker " "container ID into a file in the specified directory.",
99+
help="Store the Docker container ID into a file in the specified directory.",
98100
default=None,
99101
dest="cidfile_dir",
100102
)
@@ -112,23 +114,31 @@ def arg_parser() -> argparse.ArgumentParser:
112114
parser.add_argument(
113115
"--tmpdir-prefix",
114116
type=str,
115-
help="Path prefix for temporary directories",
117+
help="Path prefix for temporary directories. If --tmpdir-prefix is not "
118+
"provided, then the prefix for temporary directories is influenced by "
119+
"the value of the TMPDIR, TEMP, or TMP environment variables. Taking "
120+
"those into consideration, the current default is {}.".format(
121+
DEFAULT_TMP_PREFIX
122+
),
116123
default=DEFAULT_TMP_PREFIX,
117124
)
118125

119126
exgroup = parser.add_mutually_exclusive_group()
120127
exgroup.add_argument(
121128
"--tmp-outdir-prefix",
122129
type=str,
123-
help="Path prefix for intermediate output directories",
124-
default=DEFAULT_TMP_PREFIX,
130+
help="Path prefix for intermediate output directories. Defaults to the "
131+
"value of --tmpdir-prefix.",
132+
default="",
125133
)
126134

127135
exgroup.add_argument(
128136
"--cachedir",
129137
type=str,
130138
default="",
131-
help="Directory to cache intermediate workflow outputs to avoid recomputing steps.",
139+
help="Directory to cache intermediate workflow outputs to avoid "
140+
"recomputing steps. Can be very helpful in the development and "
141+
"troubleshooting of CWL documents.",
132142
)
133143

134144
exgroup = parser.add_mutually_exclusive_group()
@@ -173,7 +183,8 @@ def arg_parser() -> argparse.ArgumentParser:
173183
action="store_const",
174184
const="copy",
175185
default="move",
176-
help="Copy output files to the workflow output directory, don't delete intermediate output directories.",
186+
help="Copy output files to the workflow output directory and don't "
187+
"delete intermediate output directories.",
177188
dest="move_outputs",
178189
)
179190

@@ -196,19 +207,21 @@ def arg_parser() -> argparse.ArgumentParser:
196207

197208
parser.add_argument(
198209
"--rdf-serializer",
199-
help="Output RDF serialization format used by --print-rdf (one of turtle (default), n3, nt, xml)",
210+
help="Output RDF serialization format used by --print-rdf (one of "
211+
"turtle (default), n3, nt, xml)",
200212
default="turtle",
201213
)
202214

203215
parser.add_argument(
204216
"--eval-timeout",
205-
help="Time to wait for a Javascript expression to evaluate before giving an error, default 20s.",
217+
help="Time to wait for a Javascript expression to evaluate before giving "
218+
"an error, default 20s.",
206219
type=float,
207220
default=20,
208221
)
209222

210223
provgroup = parser.add_argument_group(
211-
"Options for recording provenance " "information of the execution"
224+
"Options for recording provenance information of the execution"
212225
)
213226
provgroup.add_argument(
214227
"--provenance",
@@ -310,7 +323,8 @@ def arg_parser() -> argparse.ArgumentParser:
310323
exgroup.add_argument(
311324
"--print-subgraph",
312325
action="store_true",
313-
help="Print workflow subgraph that will execute " "(can combine with --target)",
326+
help="Print workflow subgraph that will execute. Can combined with "
327+
"--target.",
314328
)
315329
exgroup.add_argument(
316330
"--print-targets", action="store_true", help="Print targets (output parameters)"
@@ -375,7 +389,7 @@ def arg_parser() -> argparse.ArgumentParser:
375389
parser.add_argument(
376390
"--timestamps",
377391
action="store_true",
378-
help="Add " "timestamps to the errors, warnings, and " "notifications.",
392+
help="Add timestamps to the errors, warnings, and notifications.",
379393
)
380394
parser.add_argument(
381395
"--js-console", action="store_true", help="Enable javascript console output"
@@ -388,7 +402,7 @@ def arg_parser() -> argparse.ArgumentParser:
388402
parser.add_argument(
389403
"--js-hint-options-file",
390404
type=str,
391-
help="File of options to pass to jshint."
405+
help="File of options to pass to jshint. "
392406
'This includes the added option "includewarnings". ',
393407
)
394408
dockergroup = parser.add_mutually_exclusive_group()
@@ -432,11 +446,14 @@ def arg_parser() -> argparse.ArgumentParser:
432446
conda_dependencies = argparse.SUPPRESS
433447

434448
if SOFTWARE_REQUIREMENTS_ENABLED:
435-
dependency_resolvers_configuration_help = "Dependency resolver configuration file describing how to adapt 'SoftwareRequirement' packages to current system."
449+
dependency_resolvers_configuration_help = "Dependency resolver "
450+
"configuration file describing how to adapt 'SoftwareRequirement' "
451+
"packages to current system."
436452
dependencies_directory_help = (
437453
"Defaut root directory used by dependency resolvers configuration."
438454
)
439-
use_biocontainers_help = "Use biocontainers for tools without an explicitly annotated Docker container."
455+
use_biocontainers_help = "Use biocontainers for tools without an "
456+
"explicitly annotated Docker container."
440457
conda_dependencies = (
441458
"Short cut to use Conda to resolve 'SoftwareRequirement' packages."
442459
)
@@ -477,14 +494,15 @@ def arg_parser() -> argparse.ArgumentParser:
477494
parser.add_argument(
478495
"--enable-dev",
479496
action="store_true",
480-
help="Enable loading and running development versions " "of CWL spec.",
497+
help="Enable loading and running unofficial development versions of "
498+
"the CWL standards.",
481499
default=False,
482500
)
483501

484502
parser.add_argument(
485503
"--enable-ext",
486504
action="store_true",
487-
help="Enable loading and running cwltool extensions " "to CWL spec.",
505+
help="Enable loading and running 'cwltool:' extensions to the CWL standards.",
488506
default=False,
489507
)
490508

@@ -505,7 +523,8 @@ def arg_parser() -> argparse.ArgumentParser:
505523

506524
parser.add_argument(
507525
"--default-container",
508-
help="Specify a default docker container that will be used if the workflow fails to specify one.",
526+
help="Specify a default software container to use for any "
527+
"CommandLineTool without a DockerRequirement.",
509528
)
510529
parser.add_argument(
511530
"--no-match-user",
@@ -515,8 +534,8 @@ def arg_parser() -> argparse.ArgumentParser:
515534
parser.add_argument(
516535
"--custom-net",
517536
type=str,
518-
help="Passed to `docker run` as the '--net' "
519-
"parameter when NetworkAccess is true.",
537+
help="Passed to `docker run` as the '--net' parameter when "
538+
"NetworkAccess is true, which is its default setting.",
520539
)
521540
parser.add_argument(
522541
"--disable-validate",
@@ -530,14 +549,14 @@ def arg_parser() -> argparse.ArgumentParser:
530549
exgroup.add_argument(
531550
"--enable-ga4gh-tool-registry",
532551
action="store_true",
533-
help="Enable resolution using GA4GH tool registry API",
552+
help="Enable tool resolution using GA4GH tool registry API",
534553
dest="enable_ga4gh_tool_registry",
535554
default=True,
536555
)
537556
exgroup.add_argument(
538557
"--disable-ga4gh-tool-registry",
539558
action="store_false",
540-
help="Disable resolution using GA4GH tool registry API",
559+
help="Disable tool resolution using GA4GH tool registry API",
541560
dest="enable_ga4gh_tool_registry",
542561
default=True,
543562
)
@@ -553,8 +572,9 @@ def arg_parser() -> argparse.ArgumentParser:
553572

554573
parser.add_argument(
555574
"--on-error",
556-
help="Desired workflow behavior when a step fails. One of 'stop' (do not submit any more steps) or "
557-
"'continue' (may submit other steps that are not downstream from the error). Default is 'stop'.",
575+
help="Desired workflow behavior when a step fails. One of 'stop' (do "
576+
"not submit any more steps) or 'continue' (may submit other steps that "
577+
"are not downstream from the error). Default is 'stop'.",
558578
default="stop",
559579
choices=("stop", "continue"),
560580
)
@@ -590,14 +610,14 @@ def arg_parser() -> argparse.ArgumentParser:
590610
"--force-docker-pull",
591611
action="store_true",
592612
default=False,
593-
help="Pull latest docker image even if" " it is locally present",
613+
help="Pull latest software container image even if it is locally present",
594614
dest="force_docker_pull",
595615
)
596616
parser.add_argument(
597617
"--no-read-only",
598618
action="store_true",
599619
default=False,
600-
help="Do not set root directory in the" " container as read-only",
620+
help="Do not set root directory in the container as read-only",
601621
dest="no_read_only",
602622
)
603623

@@ -612,17 +632,17 @@ def arg_parser() -> argparse.ArgumentParser:
612632
"--target",
613633
"-t",
614634
action="append",
615-
help="Only execute steps that contribute to "
616-
"listed targets (can provide more than once).",
635+
help="Only execute steps that contribute to listed targets (can be "
636+
"provided more than once).",
617637
)
618638

619639
parser.add_argument(
620640
"--mpi-config-file",
621641
type=str,
622642
default=None,
623-
help="Platform specific configuration for MPI (parallel "
624-
"launcher, its flag etc). See README section 'Running MPI-"
625-
"based tools' for details of the format.",
643+
help="Platform specific configuration for MPI (parallel launcher, its "
644+
"flag etc). See README section 'Running MPI-based tools' for details "
645+
"of the format.",
626646
)
627647

628648
parser.add_argument(
@@ -634,7 +654,7 @@ def arg_parser() -> argparse.ArgumentParser:
634654
help="path or URL to a CWL Workflow, "
635655
"CommandLineTool, or ExpressionTool. If the `inputs_object` has a "
636656
"`cwl:tool` field indicating the path or URL to the cwl_document, "
637-
" then the `workflow` argument is optional.",
657+
" then the `cwl_document` argument is optional.",
638658
)
639659
parser.add_argument(
640660
"job_order",

cwltool/command_line_tool.py

+4-11
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import os
99
import re
1010
import shutil
11-
import tempfile
1211
import threading
1312
import urllib
1413
from functools import cmp_to_key, partial
@@ -261,7 +260,7 @@ def revmap_file(
261260
return f
262261

263262
raise WorkflowException(
264-
"Output File object is missing both 'location' " "and 'path' fields: %s" % f
263+
"Output File object is missing both 'location' and 'path' fields: %s" % f
265264
)
266265

267266

@@ -936,15 +935,9 @@ def update_status_output_callback(
936935
)
937936
dockerReq, _ = self.get_requirement("DockerRequirement")
938937
if dockerReq is not None and runtimeContext.use_container:
939-
out_dir, out_prefix = os.path.split(runtimeContext.tmp_outdir_prefix)
940-
j.outdir = runtimeContext.outdir or tempfile.mkdtemp(
941-
prefix=out_prefix, dir=out_dir
942-
)
943-
tmpdir_dir, tmpdir_prefix = os.path.split(runtimeContext.tmpdir_prefix)
944-
j.tmpdir = runtimeContext.tmpdir or tempfile.mkdtemp(
945-
prefix=tmpdir_prefix, dir=tmpdir_dir
946-
)
947-
j.stagedir = tempfile.mkdtemp(prefix=tmpdir_prefix, dir=tmpdir_dir)
938+
j.outdir = runtimeContext.get_outdir()
939+
j.tmpdir = runtimeContext.get_tmpdir()
940+
j.stagedir = runtimeContext.create_tmpdir()
948941
else:
949942
j.outdir = builder.outdir
950943
j.tmpdir = builder.tmpdir

0 commit comments

Comments
 (0)