Skip to content

Commit 11487b8

Browse files
authored
Merge branch 'master' into add_exec_line
2 parents e034328 + 708ba4b commit 11487b8

File tree

373 files changed

+1910
-74304
lines changed

Some content is hidden

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

373 files changed

+1910
-74304
lines changed

CODE_OF_CONDUCT.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
CWL Code of Conduct
2+
===================
3+
4+
The CWL Project is dedicated to providing a harassment-free experience for
5+
everyone. We do not tolerate harassment of participants in any form.
6+
7+
This code of conduct applies to all CWL Project spaces both online and off: the
8+
Google Group, the Gitter chat room, the Google Hangouts chats, and any other
9+
CWL spaces. Anyone who violates this code of conduct may be sanctioned or
10+
expelled from these spaces at the discretion of the CWL Leadership Team.
11+
12+
Some CWL Project spaces may have additional rules in place, which will be
13+
made clearly available to participants. Participants are responsible for
14+
knowing and abiding by these rules.
15+
16+
Harassment includes, but is not limited to:
17+
18+
- Offensive comments related to gender, gender identity and expression, sexual
19+
orientation, disability, mental illness, neuro(a)typicality, physical
20+
appearance, body size, age, race, or religion.
21+
- Unwelcome comments regarding a person’s lifestyle choices and practices,
22+
including those related to food, health, parenting, drugs, and employment.
23+
- Deliberate misgendering or use of [dead](https://www.quora.com/What-is-deadnaming/answer/Nancy-C-Walker)
24+
or rejected names.
25+
- Gratuitous or off-topic sexual images or behaviour in spaces where they’re not
26+
appropriate.
27+
- Physical contact and simulated physical contact (eg, textual descriptions like
28+
\*hug\*” or “\*backrub\*”) without consent or after a request to stop.
29+
- Threats of violence.
30+
- Incitement of violence towards any individual, including encouraging a person
31+
to commit suicide or to engage in self-harm.
32+
- Deliberate intimidation.
33+
- Stalking or following.
34+
- Harassing photography or recording, including logging online activity for
35+
harassment purposes.
36+
- Sustained disruption of discussion.
37+
- Unwelcome sexual attention.
38+
- Pattern of inappropriate social contact, such as requesting/assuming
39+
inappropriate levels of intimacy with others
40+
- Continued one-on-one communication after requests to cease.
41+
- Deliberate “outing” of any aspect of a person’s identity without their consent
42+
except as necessary to protect vulnerable people from intentional abuse.
43+
- Publication of non-harassing private communication.
44+
45+
The CWL Project prioritizes marginalized people’s safety over privileged
46+
people’s comfort. The CWL Leadeship Team will not act on complaints regarding:
47+
48+
- ‘Reverse’ -isms, including ‘reverse racism,’ ‘reverse sexism,’ and ‘cisphobia’
49+
- Reasonable communication of boundaries, such as “leave me alone,” “go away,” or
50+
“I’m not discussing this with you.”
51+
- Communicating in a [tone](http://geekfeminism.wikia.com/wiki/Tone_argument)
52+
you don’t find congenial
53+
54+
Reporting
55+
---------
56+
57+
If you are being harassed by a member of the CWL Project, notice that someone
58+
else is being harassed, or have any other concerns, please contact the CWL
59+
Leadership Team at [email protected]. If person who is harassing
60+
you is on the team, they will recuse themselves from handling your incident. We
61+
will respond as promptly as we can.
62+
63+
This code of conduct applies to CWL Project spaces, but if you are being
64+
harassed by a member of CWL Project outside our spaces, we still want to
65+
know about it. We will take all good-faith reports of harassment by CWL Project
66+
members, especially the CWL Leadership Team, seriously. This includes harassment
67+
outside our spaces and harassment that took place at any point in time. The
68+
abuse team reserves the right to exclude people from the CWL Project based on
69+
their past behavior, including behavior outside CWL Project spaces and
70+
behavior towards people who are not in the CWL Project.
71+
72+
In order to protect volunteers from abuse and burnout, we reserve the right to
73+
reject any report we believe to have been made in bad faith. Reports intended
74+
to silence legitimate criticism may be deleted without response.
75+
76+
We will respect confidentiality requests for the purpose of protecting victims
77+
of abuse. At our discretion, we may publicly name a person about whom we’ve
78+
received harassment complaints, or privately warn third parties about them, if
79+
we believe that doing so will increase the safety of CWL Project members or
80+
the general public. We will not name harassment victims without their
81+
affirmative consent.
82+
83+
Consequences
84+
------------
85+
86+
Participants asked to stop any harassing behavior are expected to comply
87+
immediately.
88+
89+
If a participant engages in harassing behavior, the CWL Leadership Team may
90+
take any action they deem appropriate, up to and including expulsion from all
91+
CWL Project spaces and identification of the participant as a harasser to other
92+
CWL Project members or the general public.
93+
94+
This anti-harassment policy is based on the [example policy from the Geek
95+
Feminism wiki](http://geekfeminism.wikia.com/wiki/Community_anti-harassment/Policy),
96+
created by the Geek Feminism community.
97+
98+
CWL Leadership Team
99+
-------------------
100+
101+
As a stop gap measure until a more formal governance structure is adopted, the
102+
following individuals make up the leadership of the CWL Project: Peter Amstutz,
103+
John Chilton, Michael R. Crusoe, and Nebojša Tijanić.
104+
105+
To report an issue with anyone on the team you can escalate to Ward Vandewege
106+
(Curoverse) [email protected], Anton Nekrutenko (Galaxy)
107+
anton AT bx DOT psu DOT edu, C. Titus Brown (UC Davis) [email protected], or
108+
Brandi Davis-Dusenbery (Seven Bridges Genomics) [email protected].

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ include tests/wf/*
99
include tests/override/*
1010
include tests/checker_wf/*
1111
include tests/subgraph/*
12+
include tests/trs/*
1213
include cwltool/schemas/v1.0/*.yml
1314
include cwltool/schemas/v1.0/*.yml
1415
include cwltool/schemas/v1.0/*.md

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ MODULE=cwltool
2727
# `[[` conditional expressions.
2828
PYSOURCES=$(wildcard ${MODULE}/**.py tests/*.py) setup.py
2929
DEVPKGS=pycodestyle diff_cover autopep8 pylint coverage pydocstyle flake8 \
30-
pytest pytest-xdist isort
30+
pytest-xdist==1.27.0 isort wheel -rtest-requirements.txt
3131
DEBDEVPKGS=pep8 python-autopep8 pylint python-coverage pydocstyle sloccount \
3232
python-flake8 python-mock shellcheck
33-
VERSION=1.0.$(shell date +%Y%m%d%H%M%S --utc --date=`git log --first-parent \
34-
--max-count=1 --format=format:%cI`)
33+
VERSION=1.0.$(shell TZ=UTC git log --first-parent --max-count=1 \
34+
--format=format:%cd --date=format-local:%Y%m%d%H%M%S)
3535
mkfile_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
3636
UNAME_S=$(shell uname -s)
3737
ifeq ($(UNAME_S),Linux)
@@ -51,7 +51,7 @@ help: Makefile
5151

5252
## install-dep : install most of the development dependencies via pip
5353
install-dep:
54-
pip install --upgrade $(DEVPKGS) -rtest-requirements.txt
54+
pip install --upgrade $(DEVPKGS)
5555

5656
## install-deb-dep: install most of the dev dependencies via apt-get
5757
install-deb-dep:

README.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Common Workflow Language tool description reference implementation
33
==================================================================
44

5-
CWL conformance tests: |Conformance Status| |Linux Status| |Windows Status| |Coverage Status|
5+
CWL conformance tests: |Conformance Status| |Linux Status| |Windows Status| |Coverage Status| |Downloads|
66

77

88
.. |Conformance Status| image:: https://ci.commonwl.org/buildStatus/icon?job=cwltool-conformance
@@ -15,7 +15,10 @@ CWL conformance tests: |Conformance Status| |Linux Status| |Windows Status| |Cov
1515
:target: https://ci.appveyor.com/project/mr-c/cwltool
1616

1717
.. |Coverage Status| image:: https://img.shields.io/codecov/c/github/common-workflow-language/cwltool.svg
18-
:target: https://codecov.io/gh/common-workflow-language/cwltool
18+
:target: https://codecov.io/gh/common-workflow-language/cwltool
19+
20+
.. |Downloads| image:: https://pepy.tech/badge/cwltool/month
21+
:target: https://pepy.tech/project/cwltool
1922

2023
This is the reference implementation of the Common Workflow Language. It is
2124
intended to be feature complete and provide comprehensive validation of CWL
@@ -495,7 +498,7 @@ Running tests locally
495498

496499
- Running basic tests ``(/tests)``:
497500

498-
To run the basis tests after installing `cwltool` execute the following:
501+
To run the basic tests after installing `cwltool` execute the following:
499502

500503
.. code:: bash
501504

appveyor.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ install:
3232
- ps: 'Install-Product node 0.12 x64'
3333
- "set PATH=%PYTHON%\\Scripts;%PATH%"
3434
- "%PYTHON%\\python.exe -m pip install -U pip setuptools^>=20.3 wheel"
35-
- "%PYTHON%\\python.exe -m pip install -U codecov pytest-xdist pytest-cov galaxy-lib -rtest-requirements.txt"
35+
- "%PYTHON%\\python.exe -m pip install -U codecov -rtest-requirements.txt pytest-xdist==1.27 "
3636
# Note the use of a `^` to escape the `>`
3737

3838
build_script:
3939
- "%PYTHON%\\python.exe -m pip install -rrequirements.txt"
40-
- "%PYTHON%\\python.exe -m pip install -e ."
40+
- "%PYTHON%\\python.exe -m pip install -e .[deps]"
4141

4242
test_script:
4343
- |

cwl-docker.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
#!/bin/sh
2+
# Changing the line below? Update https://cloud.docker.com/u/commonworkflowlanguage/repository/docker/commonworkflowlanguage/cwltool
23
exec docker run -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -v "$PWD":"$PWD" -w="$PWD" commonworkflowlanguage/cwltool "$@"

cwltool/argparser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def arg_parser(): # type: () -> argparse.ArgumentParser
5757

5858
cidgroup.add_argument(
5959
"--cidfile-dir", type=Text, help="Store the Docker "
60-
"container ID into a file in the specifed directory.",
60+
"container ID into a file in the specified directory.",
6161
default=None, dest="cidfile_dir")
6262

6363
cidgroup.add_argument(
@@ -105,10 +105,10 @@ def arg_parser(): # type: () -> argparse.ArgumentParser
105105

106106
exgroup = parser.add_mutually_exclusive_group()
107107
exgroup.add_argument("--enable-pull", default=True, action="store_true",
108-
help="Try to pull Docker images", dest="enable_pull")
108+
help="Try to pull Docker images", dest="pull_image")
109109

110110
exgroup.add_argument("--disable-pull", default=True, action="store_false",
111-
help="Do not try to pull Docker images", dest="enable_pull")
111+
help="Do not try to pull Docker images", dest="pull_image")
112112

113113
parser.add_argument("--rdf-serializer",
114114
help="Output RDF serialization format used by --print-rdf (one of turtle (default), n3, nt, xml)",

cwltool/builder.py

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
from __future__ import absolute_import
22

33
import copy
4+
import os
45
import logging
56
from typing import (Any, Callable, Dict, List, MutableMapping, MutableSequence,
67
Optional, Set, Tuple, Union)
78

9+
from typing_extensions import Text, Type, TYPE_CHECKING # pylint: disable=unused-import
10+
# move to a regular typing import when Python 3.3-3.6 is no longer supported
11+
812
from rdflib import Graph, URIRef # pylint: disable=unused-import
913
from rdflib.namespace import OWL, RDFS
1014
from ruamel.yaml.comments import CommentedMap
1115
from schema_salad import validate
1216
from schema_salad.schema import Names, convert_to_dict
1317
from schema_salad.avro.schema import make_avsc_object, Schema
1418
from schema_salad.sourceline import SourceLine
19+
from schema_salad.ref_resolver import uri_file_path
1520
from six import iteritems, string_types
21+
from typing import IO
1622
from typing_extensions import (TYPE_CHECKING, # pylint: disable=unused-import
1723
Text, Type)
1824
# move to a regular typing import when Python 3.3-3.6 is no longer supported
@@ -22,15 +28,25 @@
2228
from .loghandler import _logger
2329
from .mutation import MutationManager # pylint: disable=unused-import
2430
from .pathmapper import PathMapper # pylint: disable=unused-import
25-
from .pathmapper import get_listing, normalizeFilesDirs, visit_class
31+
from .pathmapper import CONTENT_LIMIT, get_listing, normalizeFilesDirs, visit_class
2632
from .stdfsaccess import StdFsAccess # pylint: disable=unused-import
2733
from .utils import aslist, docker_windows_path_adjust, json_dumps, onWindows
2834

2935

3036

3137
if TYPE_CHECKING:
3238
from .provenance import ProvenanceProfile # pylint: disable=unused-import
33-
CONTENT_LIMIT = 64 * 1024
39+
40+
41+
def content_limit_respected_read_bytes(f): # type: (IO) -> bytes
42+
contents = f.read(CONTENT_LIMIT + 1)
43+
if len(contents) > CONTENT_LIMIT:
44+
raise WorkflowException("loadContents handling encountered buffer that is exceeds maximum lenght of %d bytes" % CONTENT_LIMIT)
45+
return contents
46+
47+
48+
def content_limit_respected_read(f): # type: (IO) -> Text
49+
return content_limit_respected_read_bytes(f).decode("utf-8")
3450

3551

3652
def substitute(value, replace): # type: (Text, Text) -> Text
@@ -130,7 +146,7 @@ def __init__(self,
130146
loadListing, # type: Text
131147
outdir, # type: Text
132148
tmpdir, # type: Text
133-
stagedir, # type: Text
149+
stagedir # type: Text
134150
): # type: (...) -> None
135151

136152
self.job = job
@@ -191,11 +207,16 @@ def bind_input(self,
191207
value_from_expression = False
192208
if "inputBinding" in schema and isinstance(schema["inputBinding"], MutableMapping):
193209
binding = CommentedMap(schema["inputBinding"].items())
194-
assert binding is not None
195210

196211
bp = list(aslist(lead_pos))
197212
if "position" in binding:
198-
bp.extend(aslist(binding["position"]))
213+
position = binding["position"]
214+
if isinstance(position, str): # no need to test the CWL Version
215+
# the schema for v1.0 only allow ints
216+
binding['position'] = self.do_eval(position, context=datum)
217+
bp.append(binding['position'])
218+
else:
219+
bp.extend(aslist(binding['position']))
199220
else:
200221
bp.append(0)
201222
bp.extend(aslist(tail_pos))
@@ -216,7 +237,6 @@ def bind_input(self,
216237
avsc = self.names.get_name(t["name"], "")
217238
if not avsc:
218239
avsc = make_avsc_object(convert_to_dict(t), self.names)
219-
assert avsc is not None
220240
if validate.validate(avsc, datum):
221241
schema = copy.deepcopy(schema)
222242
schema["type"] = t
@@ -278,32 +298,41 @@ def _capture_files(f):
278298
self.files.append(datum)
279299
if (binding and binding.get("loadContents")) or schema.get("loadContents"):
280300
with self.fs_access.open(datum["location"], "rb") as f:
281-
datum["contents"] = f.read(CONTENT_LIMIT).decode("utf-8")
301+
datum["contents"] = content_limit_respected_read(f)
282302

283303
if "secondaryFiles" in schema:
284304
if "secondaryFiles" not in datum:
285305
datum["secondaryFiles"] = []
286306
for sf in aslist(schema["secondaryFiles"]):
287-
if isinstance(sf, MutableMapping) or "$(" in sf or "${" in sf:
288-
sfpath = self.do_eval(sf, context=datum)
307+
if 'required' in sf:
308+
sf_required = self.do_eval(sf['required'], context=datum)
309+
else:
310+
sf_required = True
311+
312+
if "$(" in sf["pattern"] or "${" in sf["pattern"]:
313+
sfpath = self.do_eval(sf["pattern"], context=datum)
289314
else:
290-
sfpath = substitute(datum["basename"], sf)
315+
sfpath = substitute(datum["basename"], sf["pattern"])
316+
291317
for sfname in aslist(sfpath):
318+
if not sfname:
319+
continue
292320
found = False
293321
for d in datum["secondaryFiles"]:
294322
if not d.get("basename"):
295323
d["basename"] = d["location"][d["location"].rindex("/")+1:]
296324
if d["basename"] == sfname:
297325
found = True
298326
if not found:
327+
sf_location = datum["location"][0:datum["location"].rindex("/")+1]+sfname
299328
if isinstance(sfname, MutableMapping):
300329
datum["secondaryFiles"].append(sfname)
301-
elif discover_secondaryFiles:
330+
elif discover_secondaryFiles and self.fs_access.exists(sf_location):
302331
datum["secondaryFiles"].append({
303-
"location": datum["location"][0:datum["location"].rindex("/")+1]+sfname,
332+
"location": sf_location,
304333
"basename": sfname,
305334
"class": "File"})
306-
else:
335+
elif sf_required:
307336
raise WorkflowException("Missing required secondary file '%s' from file object: %s" % (
308337
sfname, json_dumps(datum, indent=4)))
309338

@@ -321,7 +350,7 @@ def _capture_files(f):
321350
visit_class(datum.get("secondaryFiles", []), ("File", "Directory"), _capture_files)
322351

323352
if schema["type"] == "Directory":
324-
ll = self.loadListing or (binding and binding.get("loadListing"))
353+
ll = schema.get("loadListing") or self.loadListing
325354
if ll and ll != "no_listing":
326355
get_listing(self.fs_access, datum, (ll == "deep_listing"))
327356
self.files.append(datum)
@@ -348,7 +377,6 @@ def tostr(self, value): # type: (Any) -> Text
348377
# docker_req is none only when there is no dockerRequirement
349378
# mentioned in hints and Requirement
350379
path = docker_windows_path_adjust(value["path"])
351-
assert path is not None
352380
return path
353381
return value["path"]
354382
else:
@@ -393,8 +421,7 @@ def generate_arg(self, binding): # type: (Dict[Text, Any]) -> List[Text]
393421
if sep:
394422
args.extend([prefix, self.tostr(j)])
395423
else:
396-
assert prefix is not None
397-
args.append(prefix + self.tostr(j))
424+
args.append("" if not prefix else prefix + self.tostr(j))
398425

399426
return [a for a in args if a is not None]
400427

0 commit comments

Comments
 (0)