diff --git a/src/runcrate/__init__.py b/src/runcrate/__init__.py index cbf4662..425029c 100644 --- a/src/runcrate/__init__.py +++ b/src/runcrate/__init__.py @@ -180,10 +180,11 @@ def get_workflow(wf_path): class ProvCrateBuilder: - def __init__(self, root, workflow_name=None, license=None): + def __init__(self, root, workflow_name=None, license=None, readme=None): self.root = Path(root) self.workflow_name = workflow_name self.license = license + self.readme = Path(readme) if readme else readme self.wf_path = self.root / "workflow" / WORKFLOW_BASENAME self.cwl_defs = get_workflow(self.wf_path) self.step_maps = self._get_step_maps(self.cwl_defs) @@ -261,6 +262,7 @@ def get_dict(self, entity): def build(self): crate = ROCrate(gen_preview=False) crate.metadata.extra_terms.update(EXTRA_TERMS) + self.add_root_metadata(crate) self.add_profiles(crate) self.add_workflow(crate) self.add_engine_run(crate) @@ -268,6 +270,15 @@ def build(self): self.patch_workflow_input_collection(crate) return crate + def add_root_metadata(self, crate): + if self.license: + crate.root_dataset["license"] = self.license + if self.readme: + readme = crate.add_file(self.readme) + readme["about"] = crate.root_dataset + if self.readme.suffix.lower() == ".md": + readme["encodingFormat"] = "text/markdown" + def add_profiles(self, crate): profiles = [] for p in "process", "workflow", "provenance": @@ -297,8 +308,6 @@ def add_workflow(self, crate): self.wf_path, self.wf_path.name, main=True, lang="cwl", lang_version=lang_version, gen_cwl=False, properties=properties ) - if self.license: - crate.root_dataset["license"] = self.license cwl_workflow = self.cwl_defs[workflow.id] workflow["input"] = self.add_params(crate, cwl_workflow.inputs) workflow["output"] = self.add_params(crate, cwl_workflow.outputs) diff --git a/src/runcrate/cli.py b/src/runcrate/cli.py index 2ef843f..7fa8119 100644 --- a/src/runcrate/cli.py +++ b/src/runcrate/cli.py @@ -47,13 +47,18 @@ def cli(): metavar="STRING", help="original workflow name", ) -def convert(root, output, license, workflow_name): +@click.option( + "--readme", + type=click.Path(exists=True, dir_okay=False, readable=True, path_type=Path), + help="path to a README file (should be README.md in Markdown format)", +) +def convert(root, output, license, workflow_name, readme): """\ RO_DIR: top-level directory of the CWLProv RO """ if not output: output = Path(f"{root.name}.crate.zip") - builder = ProvCrateBuilder(root, workflow_name, license) + builder = ProvCrateBuilder(root, workflow_name, license, readme) crate = builder.build() if output.suffix == ".zip": crate.write_zip(output) diff --git a/tests/test_cli.py b/tests/test_cli.py index b6fa766..44ba663 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -78,3 +78,14 @@ def test_cli_convert_workflow_name(data_dir, tmpdir): crate = ROCrate(crate_dir) workflow = crate.mainEntity assert workflow["name"] == workflow_name + + +def test_cli_convert_readme(data_dir, tmpdir): + root = data_dir / "revsort-run-1" + crate_dir = tmpdir / "revsort-run-1-crate" + readme = data_dir / "README.md" + runner = CliRunner() + args = ["convert", str(root), "-o", str(crate_dir), "--readme", readme] + assert runner.invoke(cli, args).exit_code == 0 + crate = ROCrate(crate_dir) + assert crate.get(readme.name) diff --git a/tests/test_cwlprov_crate_builder.py b/tests/test_cwlprov_crate_builder.py index 60a6318..602c07d 100644 --- a/tests/test_cwlprov_crate_builder.py +++ b/tests/test_cwlprov_crate_builder.py @@ -29,11 +29,17 @@ def test_revsort(data_dir, tmpdir): root = data_dir / "revsort-run-1" output = tmpdir / "revsort-run-1-crate" license = "Apache-2.0" + readme = data_dir / "README.md" workflow_name = "RevSort" - builder = ProvCrateBuilder(root, workflow_name=workflow_name, license=license) + builder = ProvCrateBuilder(root, workflow_name=workflow_name, license=license, readme=readme) crate = builder.build() crate.write(output) assert crate.root_dataset["license"] == "Apache-2.0" + readme_f = crate.get(readme.name) + assert readme_f + assert readme_f.type == "File" + assert readme_f["encodingFormat"] == "text/markdown" + assert readme_f["about"] is crate.root_dataset workflow = crate.mainEntity assert workflow.id == "packed.cwl" assert workflow["name"] == "RevSort" @@ -136,6 +142,7 @@ def test_revsort(data_dir, tmpdir): assert (output / rev_output_file.id).read_text() == rev_out_text out_text = (root / "data/b9/b9214658cc453331b62c2282b772a5c063dbd284").read_text() assert (output / wf_output_file.id).read_text() == out_text + assert (output / readme.name).read_text() == readme.read_text() # declared profile conformance proc_prof = crate.get("https://w3id.org/ro/wfrun/process/0.1") wf_prof = crate.get("https://w3id.org/ro/wfrun/workflow/0.1")