Skip to content

Commit 9597044

Browse files
committed
unify and fix tempdir creation logic
1 parent 98c3e76 commit 9597044

24 files changed

+308
-160
lines changed

Makefile

+4-1
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)

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/command_line_tool.py

+3-10
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
@@ -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

cwltool/context.py

+31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""Shared context objects that replace use of kwargs."""
22
import copy
3+
import os
4+
import tempfile
35
import threading
46
from typing import IO, Any, Callable, Dict, Iterable, List, Optional, TextIO, Union
57

@@ -148,6 +150,35 @@ def __init__(self, kwargs: Optional[Dict[str, Any]] = None) -> None:
148150
self.default_stderr = None # type: Optional[Union[IO[bytes], TextIO]]
149151
super(RuntimeContext, self).__init__(kwargs)
150152

153+
def get_outdir(self) -> str:
154+
"""Return self.outdir or create one with self.tmp_outdir_prefix."""
155+
if self.outdir:
156+
return self.outdir
157+
return self.create_outdir()
158+
159+
def get_tmpdir(self) -> str:
160+
"""Return self.tmpdir or create one with self.tmpdir_prefix."""
161+
if self.tmpdir:
162+
return self.tmpdir
163+
return self.create_tmpdir()
164+
165+
def get_stagedir(self) -> str:
166+
"""Return self.stagedir or create one with self.tmpdir_prefix."""
167+
if self.stagedir:
168+
return self.stagedir
169+
tmp_dir, tmp_prefix = os.path.split(self.tmpdir_prefix)
170+
return tempfile.mkdtemp(prefix=tmp_prefix, dir=tmp_dir)
171+
172+
def create_tmpdir(self) -> str:
173+
"""Create a temporary directory that respects self.tmpdir_prefix."""
174+
tmp_dir, tmp_prefix = os.path.split(self.tmpdir_prefix)
175+
return tempfile.mkdtemp(prefix=tmp_prefix, dir=tmp_dir)
176+
177+
def create_outdir(self) -> str:
178+
"""Create a temporary directory that respects self.tmp_outdir_prefix."""
179+
out_dir, out_prefix = os.path.split(self.tmp_outdir_prefix)
180+
return tempfile.mkdtemp(prefix=out_prefix, dir=out_dir)
181+
151182
def copy(self):
152183
# type: () -> RuntimeContext
153184
return copy.copy(self)

cwltool/docker.py

+10-16
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import shutil
88
import subprocess # nosec
99
import sys
10-
import tempfile
1110
import threading
1211
from distutils import spawn
1312
from io import StringIO, open # pylint: disable=redefined-builtin
@@ -23,10 +22,9 @@
2322
from .loghandler import _logger
2423
from .pathmapper import MapperEnt, PathMapper
2524
from .utils import (
26-
DEFAULT_TMP_PREFIX,
2725
CWLObjectType,
26+
create_tmp_dir,
2827
docker_windows_path_adjust,
29-
ensure_non_writable,
3028
ensure_writable,
3129
onWindows,
3230
)
@@ -109,8 +107,8 @@ def __init__(
109107
def get_image(
110108
docker_requirement: Dict[str, str],
111109
pull_image: bool,
112-
force_pull: bool = False,
113-
tmp_outdir_prefix: str = DEFAULT_TMP_PREFIX,
110+
force_pull: bool,
111+
tmp_outdir_prefix: str,
114112
) -> bool:
115113
"""
116114
Retrieve the relevant Docker container image.
@@ -170,7 +168,7 @@ def get_image(
170168
subprocess.check_call(cmd, stdout=sys.stderr) # nosec
171169
found = True
172170
elif "dockerFile" in docker_requirement:
173-
dockerfile_dir = str(tempfile.mkdtemp(prefix=tmp_outdir_prefix))
171+
dockerfile_dir = create_tmp_dir(tmp_outdir_prefix)
174172
with open(os.path.join(dockerfile_dir, "Dockerfile"), "wb") as dfile:
175173
dfile.write(docker_requirement["dockerFile"].encode("utf-8"))
176174
cmd = [
@@ -236,8 +234,8 @@ def get_from_requirements(
236234
self,
237235
r: CWLObjectType,
238236
pull_image: bool,
239-
force_pull: bool = False,
240-
tmp_outdir_prefix: str = DEFAULT_TMP_PREFIX,
237+
force_pull: bool,
238+
tmp_outdir_prefix: str,
241239
) -> Optional[str]:
242240
if not spawn.find_executable("docker"):
243241
raise WorkflowException("docker executable is not available")
@@ -294,8 +292,7 @@ def add_writable_file_volume(
294292
os.makedirs(os.path.dirname(host_outdir_tgt))
295293
shutil.copy(volume.resolved, host_outdir_tgt)
296294
else:
297-
tmp_dir, tmp_prefix = os.path.split(tmpdir_prefix)
298-
tmpdir = tempfile.mkdtemp(prefix=tmp_prefix, dir=tmp_dir)
295+
tmpdir = create_tmp_dir(tmpdir_prefix)
299296
file_copy = os.path.join(tmpdir, os.path.basename(volume.resolved))
300297
shutil.copy(volume.resolved, file_copy)
301298
self.append_volume(runtime, file_copy, volume.target, writable=True)
@@ -312,9 +309,8 @@ def add_writable_directory_volume(
312309
if volume.resolved.startswith("_:"):
313310
# Synthetic directory that needs creating first
314311
if not host_outdir_tgt:
315-
tmp_dir, tmp_prefix = os.path.split(tmpdir_prefix)
316312
new_dir = os.path.join(
317-
tempfile.mkdtemp(prefix=tmp_prefix, dir=tmp_dir),
313+
create_tmp_dir(tmpdir_prefix),
318314
os.path.basename(volume.target),
319315
)
320316
self.append_volume(runtime, new_dir, volume.target, writable=True)
@@ -327,8 +323,7 @@ def add_writable_directory_volume(
327323
)
328324
else:
329325
if not host_outdir_tgt:
330-
tmp_dir, tmp_prefix = os.path.split(tmpdir_prefix)
331-
tmpdir = tempfile.mkdtemp(prefix=tmp_prefix, dir=tmp_dir)
326+
tmpdir = create_tmp_dir(tmpdir_prefix)
332327
new_dir = os.path.join(tmpdir, os.path.basename(volume.resolved))
333328
shutil.copytree(volume.resolved, new_dir)
334329
self.append_volume(runtime, new_dir, volume.target, writable=True)
@@ -434,8 +429,7 @@ def create_runtime(
434429
)
435430
exit(2)
436431
else:
437-
tmp_dir, tmp_prefix = os.path.split(runtimeContext.tmpdir_prefix)
438-
cidfile_dir = tempfile.mkdtemp(prefix=tmp_prefix, dir=tmp_dir)
432+
cidfile_dir = runtimeContext.create_tmpdir()
439433

440434
cidfile_name = datetime.datetime.now().strftime("%Y%m%d%H%M%S-%f") + ".cid"
441435
if runtimeContext.cidfile_prefix is not None:

cwltool/executors.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import logging
55
import math
66
import os
7-
import tempfile
87
import threading
98
from abc import ABCMeta, abstractmethod
109
from threading import Lock
@@ -32,7 +31,7 @@
3231
from .mutation import MutationManager
3332
from .process import Process, cleanIntermediate, relocateOutputs
3433
from .provenance_profile import ProvenanceProfile
35-
from .utils import DEFAULT_TMP_PREFIX, CWLObjectType, JobsType
34+
from .utils import CWLObjectType, JobsType
3635
from .workflow import Workflow
3736
from .workflow_job import WorkflowJob, WorkflowJobStep
3837

@@ -99,9 +98,7 @@ def check_for_abstract_op(tool: CWLObjectType) -> None:
9998
if isinstance(original_outdir, str):
10099
finaloutdir = os.path.abspath(original_outdir)
101100
runtime_context = runtime_context.copy()
102-
outdir = tempfile.mkdtemp(
103-
prefix=getdefault(runtime_context.tmp_outdir_prefix, DEFAULT_TMP_PREFIX)
104-
)
101+
outdir = runtime_context.create_outdir()
105102
self.output_dirs.add(outdir)
106103
runtime_context.outdir = outdir
107104
runtime_context.mutation_manager = MutationManager()

cwltool/job.py

+8-16
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from typing import (
1818
IO,
1919
Callable,
20-
Dict,
2120
Iterable,
2221
List,
2322
Match,
@@ -38,20 +37,20 @@
3837
from typing_extensions import TYPE_CHECKING
3938

4039
from .builder import Builder, HasReqsHints
41-
from .context import RuntimeContext, getdefault
40+
from .context import RuntimeContext
4241
from .errors import UnsupportedRequirement, WorkflowException
4342
from .loghandler import _logger
4443
from .pathmapper import MapperEnt, PathMapper
4544
from .process import stage_files
4645
from .secrets import SecretStore
4746
from .utils import (
48-
DEFAULT_TMP_PREFIX,
4947
CWLObjectType,
5048
CWLOutputType,
5149
DirectoryType,
5250
OutputCallbackType,
5351
bytes2str_in_dicts,
5452
copytree_with_merge,
53+
create_tmp_dir,
5554
ensure_non_writable,
5655
ensure_writable,
5756
onWindows,
@@ -380,11 +379,7 @@ def _execute(
380379
stderr_path=stderr_path,
381380
env=env,
382381
cwd=self.outdir,
383-
job_dir=tempfile.mkdtemp(
384-
prefix=getdefault(
385-
runtimeContext.tmp_outdir_prefix, DEFAULT_TMP_PREFIX
386-
)
387-
),
382+
job_dir=runtimeContext.create_outdir(),
388383
job_script_contents=job_script_contents,
389384
timelimit=self.timelimit,
390385
name=self.name,
@@ -600,8 +595,8 @@ def get_from_requirements(
600595
self,
601596
r: CWLObjectType,
602597
pull_image: bool,
603-
force_pull: bool = False,
604-
tmp_outdir_prefix: str = DEFAULT_TMP_PREFIX,
598+
force_pull: bool,
599+
tmp_outdir_prefix: str,
605600
) -> Optional[str]:
606601
pass
607602

@@ -656,9 +651,8 @@ def create_file_and_add_volume(
656651
) -> str:
657652
"""Create the file and add a mapping."""
658653
if not host_outdir_tgt:
659-
tmp_dir, tmp_prefix = os.path.split(tmpdir_prefix)
660654
new_file = os.path.join(
661-
tempfile.mkdtemp(prefix=tmp_prefix, dir=tmp_dir),
655+
create_tmp_dir(tmpdir_prefix),
662656
os.path.basename(volume.target),
663657
)
664658
writable = True if volume.type == "CreateWritableFile" else False
@@ -770,10 +764,8 @@ def run(
770764
self.get_from_requirements(
771765
docker_req,
772766
runtimeContext.pull_image,
773-
getdefault(runtimeContext.force_docker_pull, False),
774-
getdefault(
775-
runtimeContext.tmp_outdir_prefix, DEFAULT_TMP_PREFIX
776-
),
767+
runtimeContext.force_docker_pull,
768+
runtimeContext.tmp_outdir_prefix,
777769
)
778770
)
779771
if img_id is None:

cwltool/load_tool.py

-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import uuid
99
from typing import (
1010
Any,
11-
Callable,
1211
Dict,
1312
List,
1413
MutableMapping,
@@ -21,7 +20,6 @@
2120

2221
from ruamel.yaml.comments import CommentedMap, CommentedSeq
2322
from schema_salad.exceptions import ValidationException
24-
from schema_salad.fetcher import Fetcher
2523
from schema_salad.ref_resolver import Loader, file_uri
2624
from schema_salad.schema import validate_doc
2725
from schema_salad.sourceline import SourceLine, cmap

cwltool/main.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python3
2+
# PYTHON_ARGCOMPLETE_OK
23
"""Entry point for cwltool."""
34

4-
import argcomplete
55
import argparse
66
import functools
77
import io
@@ -30,6 +30,7 @@
3030
cast,
3131
)
3232

33+
import argcomplete
3334
import coloredlogs
3435
import pkg_resources # part of setuptools
3536
from ruamel import yaml
@@ -102,8 +103,6 @@
102103
)
103104
from .workflow import Workflow
104105

105-
# PYTHON_ARGCOMPLETE_OK
106-
107106

108107
def _terminate_processes() -> None:
109108
"""Kill all spawned processes.

cwltool/pack.py

-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
Any,
77
Callable,
88
Dict,
9-
List,
109
MutableMapping,
1110
MutableSequence,
1211
Optional,
@@ -20,7 +19,6 @@
2019

2120
from .context import LoadingContext
2221
from .load_tool import fetch_document, resolve_and_validate_document
23-
from .loghandler import _logger
2422
from .process import shortname, uniquename
2523
from .update import ORDERED_VERSIONS, update
2624
from .utils import CWLObjectType, CWLOutputType

cwltool/pathmapper.py

+2-24
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,15 @@
44
import stat
55
import urllib
66
import uuid
7-
from typing import (
8-
Callable,
9-
Dict,
10-
Iterator,
11-
List,
12-
MutableMapping,
13-
MutableSequence,
14-
Optional,
15-
Set,
16-
Text,
17-
Tuple,
18-
Union,
19-
cast,
20-
)
7+
from typing import Dict, Iterator, List, Optional, Tuple, cast
218

229
from schema_salad.exceptions import ValidationException
2310
from schema_salad.ref_resolver import uri_file_path
2411
from schema_salad.sourceline import SourceLine
2512

2613
from .loghandler import _logger
2714
from .stdfsaccess import abspath
28-
from .utils import (
29-
CWLObjectType,
30-
DirectoryType,
31-
adjustDirObjs,
32-
adjustFileObjs,
33-
convert_pathsep_to_unix,
34-
dedup,
35-
downloadHttpFile,
36-
visit_class,
37-
)
15+
from .utils import CWLObjectType, convert_pathsep_to_unix, dedup, downloadHttpFile
3816

3917
MapperEnt = collections.namedtuple(
4018
"MapperEnt", ["resolved", "target", "type", "staged"]

0 commit comments

Comments
 (0)