Skip to content

Commit 7b77c4d

Browse files
author
Anton Khodak
committed
Merge branch 'master' into parallel-exec
2 parents c693396 + f691bf1 commit 7b77c4d

31 files changed

+745
-174
lines changed

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ include gittaggers.py Makefile cwltool.py
22
include tests/*
33
include tests/tmp1/tmp2/tmp3/.gitkeep
44
include tests/wf/*
5+
include tests/override/*
56
include cwltool/schemas/v1.0/*.yml
67
include cwltool/schemas/draft-2/*.yml
78
include cwltool/schemas/draft-3/*.yml

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pydocstyle_report.txt: $(PYSOURCES)
8989
pydocstyle setup.py $^ > pydocstyle_report.txt 2>&1 || true
9090

9191
diff_pydocstyle_report: pydocstyle_report.txt
92-
diff-quality --violations=pep8 $^
92+
diff-quality --violations=pycodestyle $^
9393

9494
## autopep8 : fix most Python code indentation and formatting
9595
autopep8: $(PYSOURCES)
@@ -160,7 +160,7 @@ mypy2: ${PYSOURCES}
160160
rm -Rf typeshed/2and3/schema_salad
161161
ln -s $(shell python -c 'from __future__ import print_function; import schema_salad; import os.path; print(os.path.dirname(schema_salad.__file__))') \
162162
typeshed/2and3/schema_salad
163-
MYPYPATH=$MYPYPATH:typeshed/2.7:typeshed/2and3 mypy --py2 --disallow-untyped-calls \
163+
MYPYPATH=$$MYPYPATH:typeshed/2.7:typeshed/2and3 mypy --py2 --disallow-untyped-calls \
164164
--warn-redundant-casts \
165165
cwltool
166166

@@ -171,7 +171,7 @@ mypy3: ${PYSOURCES}
171171
rm -Rf typeshed/2and3/schema_salad
172172
ln -s $(shell python3 -c 'from __future__ import print_function; import schema_salad; import os.path; print(os.path.dirname(schema_salad.__file__))') \
173173
typeshed/2and3/schema_salad
174-
MYPYPATH=$MYPYPATH:typeshed/3:typeshed/2and3 mypy --disallow-untyped-calls \
174+
MYPYPATH=$$MYPYPATH:typeshed/3:typeshed/2and3 mypy --disallow-untyped-calls \
175175
--warn-redundant-casts \
176176
cwltool
177177

README.rst

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ It is highly recommended to setup virtual environment before installing `cwltool
3131
virtualenv -p python2 venv # Create a virtual environment, can use `python3` as well
3232
source venv/bin/activate # Activate environment before installing `cwltool`
3333
34-
1. Installing the official package from PyPi (will install "cwltool" package as
34+
Installing the official package from PyPi (will install "cwltool" package as
3535
well)
3636

3737
.. code:: bash
@@ -44,7 +44,7 @@ If installing alongside another CWL implementation then
4444
4545
pip install cwltool
4646
47-
2. To install from source
47+
Or you can install from source:
4848

4949
.. code:: bash
5050
@@ -62,9 +62,16 @@ Running tests locally
6262

6363
- Running basic tests ``(/tests)``:
6464

65-
We use `tox <https://github.com/common-workflow-language/cwltool/tree/master/tox.ini>`_
66-
to run various tests in all supported Python environments.
67-
You can run the test suite by simply running the following in the terminal:
65+
To run the basis tests after installing `cwltool` execute the following:
66+
67+
.. code:: bash
68+
69+
pip install pytest mock
70+
py.test --ignore cwltool/schemas/ --pyarg cwltool
71+
72+
To run various tests in all supported Python environments we use `tox <https://github.com/common-workflow-language/cwltool/tree/master/tox.ini>`_. To run the test suite in all supported Python environments
73+
first downloading the complete code repository (see the ``git clone`` instructions above) and then run
74+
the following in the terminal:
6875
``pip install tox; tox``
6976

7077
List of all environment can be seen using:
@@ -106,6 +113,21 @@ and ``--tmp-outdir-prefix`` to somewhere under ``/Users``::
106113
.. |Build Status| image:: https://ci.commonwl.org/buildStatus/icon?job=cwltool-conformance
107114
:target: https://ci.commonwl.org/job/cwltool-conformance/
108115

116+
Running user-space implementations of Docker
117+
--------------------------------------------
118+
119+
Some compute environments disallow user-space installation of Docker due to incompatiblities in libraries or to meet security requirements. The CWL reference supports using a user space implementation with the `--user-space-docker-cmd` option.
120+
121+
Example using `dx-docker` (https://wiki.dnanexus.com/Developer-Tutorials/Using-Docker-Images):
122+
123+
For use on Linux, install the DNAnexus toolkit (see https://wiki.dnanexus.com/Downloads for instructions).
124+
125+
Run `cwltool` just as you normally would, but with the new option, e.g. from the conformance tests:
126+
127+
.. code:: bash
128+
129+
cwltool --user-space-docker-cmd=dx-docker --outdir=/tmp/tmpidytmp v1.0/test-cwl-out2.cwl v1.0/empty.json
130+
109131
Tool or workflow loading from remote or local locations
110132
-------------------------------------------------------
111133

@@ -369,6 +391,50 @@ at the following links:
369391
- `Specifications - Implementation <https://github.com/galaxyproject/galaxy/commit/81d71d2e740ee07754785306e4448f8425f890bc>`__
370392
- `Initial cwltool Integration Pull Request <https://github.com/common-workflow-language/cwltool/pull/214>`__
371393

394+
Overriding workflow requirements at load time
395+
---------------------------------------------
396+
397+
Sometimes a workflow needs additional requirements to run in a particular
398+
environment or with a particular dataset. To avoid the need to modify the
399+
underlying workflow, cwltool supports requirement "overrides".
400+
401+
The format of the "overrides" object is a mapping of item identifier (workflow,
402+
workflow step, or command line tool) followed by a list of ProcessRequirements
403+
that should be applied.
404+
405+
.. code:: yaml
406+
407+
cwltool:overrides:
408+
echo.cwl:
409+
- class: EnvVarRequirement
410+
envDef:
411+
MESSAGE: override_value
412+
413+
414+
Overrides can be specified either on the command line, or as part of the job
415+
input document. Workflow steps are identified using the name of the workflow
416+
file followed by the step name as a document fragment identifier "#id".
417+
Override identifiers are relative to the toplevel workflow document.
418+
419+
.. code:: bash
420+
421+
cwltool --overrides overrides.yml my-tool.cwl my-job.yml
422+
423+
.. code:: yaml
424+
425+
input_parameter1: value1
426+
input_parameter2: value2
427+
cwltool:overrides:
428+
workflow.cwl#step1:
429+
- class: EnvVarRequirement
430+
envDef:
431+
MESSAGE: override_value
432+
433+
.. code:: bash
434+
435+
cwltool my-tool.cwl my-job-with-overrides.yml
436+
437+
372438
CWL Tool Control Flow
373439
---------------------
374440

@@ -500,18 +566,3 @@ logger_handler
500566
logging.Handler
501567

502568
Handler object for logging.
503-
504-
Running user-space implementations of Docker
505-
--------------------------------------------
506-
507-
Some compute environments disallow user-space installation of Docker due to incompatiblities in libraries or to meet security requirements. The CWL reference supports using a user space implementation with the `--user-space-docker-cmd` option.
508-
509-
Example using `dx-docker` (https://wiki.dnanexus.com/Developer-Tutorials/Using-Docker-Images):
510-
511-
For use on Linux, install the DNAnexus toolkit (see https://wiki.dnanexus.com/Downloads for instructions).
512-
513-
Run `cwltool` just as you normally would, but with the new option, e.g. from the conformance tests:
514-
515-
```
516-
cwltool --user-space-docker-cmd=dx-docker --outdir=/tmp/tmpidytmp v1.0/test-cwl-out2.cwl v1.0/empty.json
517-
```

cwltool/draft2tool.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
from __future__ import absolute_import
22
import copy
33
import hashlib
4+
import locale
45
import json
56
import logging
67
import os
78
import re
89
import shutil
910
import tempfile
10-
from functools import partial
11-
from typing import Any, Callable, Dict, Generator, List, Optional, Set, Text, Union, cast
11+
from functools import partial, cmp_to_key
12+
from typing import (Any, Callable, Dict, Generator, List, Optional, Set, Text,
13+
Union, cast)
1214

1315
from six import string_types, u
1416

@@ -208,7 +210,7 @@ def makeJobRunner(self, use_container=True, **kwargs): # type: (Optional[bool],
208210
})
209211
dockerReq = self.requirements[0]
210212
if default_container == windows_default_container_id and use_container and onWindows():
211-
_logger.warning(DEFAULT_CONTAINER_MSG%(windows_default_container_id, windows_default_container_id))
213+
_logger.warning(DEFAULT_CONTAINER_MSG % (windows_default_container_id, windows_default_container_id))
212214

213215
if dockerReq and use_container:
214216
return DockerCommandLineJob()
@@ -523,8 +525,8 @@ def collect_output_ports(self, ports, builder, outdir, compute_checksum=True, jo
523525
for i, port in enumerate(ports):
524526
def makeWorkflowException(msg):
525527
return WorkflowException(
526-
u"Error collecting output for parameter '%s':\n%s"
527-
% (shortname(port["id"]), msg))
528+
u"Error collecting output for parameter '%s':\n%s"
529+
% (shortname(port["id"]), msg))
528530
with SourceLine(ports, i, makeWorkflowException, debug):
529531
fragment = shortname(port["id"])
530532
ret[fragment] = self.collect_output(port, builder, outdir, fs_access,
@@ -575,16 +577,25 @@ def collect_output(self, schema, builder, outdir, fs_access, compute_checksum=Tr
575577
elif gb == ".":
576578
gb = outdir
577579
elif gb.startswith("/"):
578-
raise WorkflowException("glob patterns must not start with '/'")
580+
raise WorkflowException(
581+
"glob patterns must not start with '/'")
579582
try:
580583
prefix = fs_access.glob(outdir)
581584
r.extend([{"location": g,
582-
"path": fs_access.join(builder.outdir, g[len(prefix[0])+1:]),
585+
"path": fs_access.join(builder.outdir,
586+
g[len(prefix[0])+1:]),
583587
"basename": os.path.basename(g),
584-
"nameroot": os.path.splitext(os.path.basename(g))[0],
585-
"nameext": os.path.splitext(os.path.basename(g))[1],
586-
"class": "File" if fs_access.isfile(g) else "Directory"}
587-
for g in fs_access.glob(fs_access.join(outdir, gb))])
588+
"nameroot": os.path.splitext(
589+
os.path.basename(g))[0],
590+
"nameext": os.path.splitext(
591+
os.path.basename(g))[1],
592+
"class": "File" if fs_access.isfile(g)
593+
else "Directory"}
594+
for g in sorted(fs_access.glob(
595+
fs_access.join(outdir, gb)),
596+
key=cmp_to_key(cast(
597+
Callable[[Text, Text],
598+
int], locale.strcoll)))])
588599
except (OSError, IOError) as e:
589600
_logger.warning(Text(e))
590601
except:

0 commit comments

Comments
 (0)