diff --git a/rocrate/model/computerlanguage.py b/rocrate/model/computerlanguage.py index fdb5872..014bdc0 100644 --- a/rocrate/model/computerlanguage.py +++ b/rocrate/model/computerlanguage.py @@ -69,109 +69,116 @@ def version(self, version): self["version"] = version -# For workflow ro-crates. Note that -# https://about.workflowhub.eu/Workflow-RO-Crate/ does not specify versions. +# See https://w3id.org/workflowhub/workflow-ro-crate/1.0 +# (note that it does not specify "version") -CWL_DEFAULT_VERSION = "1.2" -# https://github.com/galaxyproject/gxformat2 has some info on gxformat2 versions -# version can probably be simply ignored for "native" *.ga workflows -GALAXY_DEFAULT_VERSION = "21.09" -KNIME_DEFAULT_VERSION = "4.5.0" -NEXTFLOW_DEFAULT_VERSION = "21.10" -SNAKEMAKE_DEFAULT_VERSION = "6.13" -COMPSS_DEFAULT_VERSION = "2.10" -AUTOSUBMIT_DEFAULT_VERSION = "3.14" - -def cwl(crate, version=CWL_DEFAULT_VERSION): +def cwl(crate, version=None): id_ = "https://w3id.org/workflowhub/workflow-ro-crate#cwl" - return ComputerLanguage(crate, identifier=id_, properties={ + identifier = "https://w3id.org/cwl/" + if version: + identifier = f"{identifier}v{version}/" + properties = { "name": "Common Workflow Language", "alternateName": "CWL", "identifier": { - "@id": f"https://w3id.org/cwl/{version}/" + "@id": identifier }, "url": { "@id": "https://www.commonwl.org/" }, - "version": version - }) + } + if version: + properties["version"] = version + return ComputerLanguage(crate, identifier=id_, properties=properties) -def galaxy(crate, version=GALAXY_DEFAULT_VERSION): +def galaxy(crate, version=None): id_ = "https://w3id.org/workflowhub/workflow-ro-crate#galaxy" - return ComputerLanguage(crate, identifier=id_, properties={ + properties = { "name": "Galaxy", "identifier": { "@id": "https://galaxyproject.org/" }, "url": { "@id": "https://galaxyproject.org/" - }, - "version": version - }) + } + } + if version: + properties["version"] = version + return ComputerLanguage(crate, identifier=id_, properties=properties) -def knime(crate, version=KNIME_DEFAULT_VERSION): +def knime(crate, version=None): id_ = "https://w3id.org/workflowhub/workflow-ro-crate#knime" - return ComputerLanguage(crate, identifier=id_, properties={ + properties = { "name": "KNIME", "identifier": { "@id": "https://www.knime.com/" }, "url": { "@id": "https://www.knime.com/" - }, - "version": version - }) + } + } + if version: + properties["version"] = version + return ComputerLanguage(crate, identifier=id_, properties=properties) -def nextflow(crate, version=NEXTFLOW_DEFAULT_VERSION): +def nextflow(crate, version=None): id_ = "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" - return ComputerLanguage(crate, identifier=id_, properties={ + properties = { "name": "Nextflow", "identifier": { "@id": "https://www.nextflow.io/" }, "url": { "@id": "https://www.nextflow.io/" - }, - "version": version - }) + } + } + if version: + properties["version"] = version + return ComputerLanguage(crate, identifier=id_, properties=properties) -def snakemake(crate, version=SNAKEMAKE_DEFAULT_VERSION): +def snakemake(crate, version=None): id_ = "https://w3id.org/workflowhub/workflow-ro-crate#snakemake" - return ComputerLanguage(crate, identifier=id_, properties={ + properties = { "name": "Snakemake", "identifier": { "@id": "https://doi.org/10.1093/bioinformatics/bts480" }, "url": { "@id": "https://snakemake.readthedocs.io" - }, - "version": version - }) + } + } + if version: + properties["version"] = version + return ComputerLanguage(crate, identifier=id_, properties=properties) -def compss(crate, version=COMPSS_DEFAULT_VERSION): - return ComputerLanguage(crate, identifier="#compss", properties={ +def compss(crate, version=None): + properties = { "name": "COMPSs Programming Model", "alternateName": "COMPSs", "url": "http://compss.bsc.es/", - "citation": "https://doi.org/10.1007/s10723-013-9272-5", - "version": version - }) + "citation": "https://doi.org/10.1007/s10723-013-9272-5" + } + if version: + properties["version"] = version + return ComputerLanguage(crate, identifier="#compss", properties=properties) -def autosubmit(crate, version=AUTOSUBMIT_DEFAULT_VERSION): - return ComputerLanguage(crate, identifier="#autosubmit", properties={ +def autosubmit(crate, version=None): + properties = { "name": "Autosubmit", "alternateName": "AS", "url": "https://autosubmit.readthedocs.io/", - "citation": "https://doi.org/10.1109/HPCSim.2016.7568429", - "version": version - }) + "citation": "https://doi.org/10.1109/HPCSim.2016.7568429" + } + if version: + properties["version"] = version + return ComputerLanguage(crate, identifier="#autosubmit", properties=properties) LANG_MAP = { @@ -190,4 +197,4 @@ def get_lang(crate, name, version=None): func = LANG_MAP[name.lower()] except KeyError: raise ValueError(f"Unknown language: {name}") - return func(crate, version=version) if version else func(crate) + return func(crate, version=version) diff --git a/rocrate/rocrate.py b/rocrate/rocrate.py index 79a5955..e209495 100644 --- a/rocrate/rocrate.py +++ b/rocrate/rocrate.py @@ -438,8 +438,7 @@ def add_workflow( if isinstance(lang, ComputerLanguage): assert lang.crate is self else: - kwargs = {"version": lang_version} if lang_version else {} - lang = get_lang(self, lang, **kwargs) + lang = get_lang(self, lang, version=lang_version) self.add(lang) lang_str = lang.id.rsplit("#", 1)[1] workflow.lang = lang diff --git a/test/test_workflow_ro_crate.py b/test/test_workflow_ro_crate.py index 13d232e..6deed65 100644 --- a/test/test_workflow_ro_crate.py +++ b/test/test_workflow_ro_crate.py @@ -16,8 +16,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +import pytest + from rocrate.rocrate import ROCrate, make_workflow_rocrate -from rocrate.model.computerlanguage import CWL_DEFAULT_VERSION, GALAXY_DEFAULT_VERSION WF_CRATE = "https://w3id.org/workflowhub/workflow-ro-crate" @@ -33,7 +34,7 @@ def test_galaxy_wf_crate(test_data_dir, tmpdir, helpers): assert wf_crate.mainEntity is wf lang = wf_crate.dereference(f"{WF_CRATE}#galaxy") assert hasattr(lang, "name") - assert lang.version == GALAXY_DEFAULT_VERSION + assert "version" not in lang assert wf.get("programmingLanguage") is lang assert wf.get("subjectOf") is not None assert helpers.WORKFLOW_DESC_TYPES.issubset(wf["subjectOf"].type) @@ -68,7 +69,7 @@ def test_cwl_wf_crate(test_data_dir, tmpdir, helpers): assert wf_crate.mainEntity is wf lang = wf_crate.dereference(f"{WF_CRATE}#cwl") assert hasattr(lang, "name") - assert lang.version == CWL_DEFAULT_VERSION + assert "version" not in lang assert wf.get("programmingLanguage") is lang assert "subjectOf" not in wf @@ -99,7 +100,7 @@ def test_create_wf_include(test_data_dir, tmpdir, helpers): assert wf_crate.mainEntity is wf lang = wf_crate.dereference(f"{WF_CRATE}#galaxy") assert hasattr(lang, "name") - assert lang.version == GALAXY_DEFAULT_VERSION + assert "version" not in lang assert wf.get("programmingLanguage") is lang assert wf.get("subjectOf") is not None assert helpers.WORKFLOW_DESC_TYPES.issubset(wf["subjectOf"].type) @@ -124,3 +125,19 @@ def test_create_wf_include(test_data_dir, tmpdir, helpers): assert file2.exists() with open(extra_file2) as f1, open(file2) as f2: assert f1.read() == f2.read() + + +@pytest.mark.parametrize("lang_version", [None, "1.2"]) +def test_cwl_lang_version(test_data_dir, lang_version): + wf_id = 'sample_cwl_wf.cwl' + wf_path = test_data_dir / wf_id + crate = ROCrate() + workflow = crate.add_workflow(wf_path, wf_id, lang_version=lang_version) + lang = workflow["programmingLanguage"] + lang_id = lang["identifier"] + if lang_version is None: + assert lang_id == "https://w3id.org/cwl/" + assert "version" not in lang + else: + assert lang_id == "https://w3id.org/cwl/v1.2/" + assert lang["version"] == "1.2"