Repository: ResearchObject/ro-crate-py
Pull request #54 (2021-03-30 14:41:55)

Optional preview generation
Makes preview generation optional in all modes (create, init, read).


Patch:
diff --git a/rocrate/cli.py b/rocrate/cli.py
index 7256978..df6369b 100644
--- a/rocrate/cli.py
+++ b/rocrate/cli.py
@@ -20,7 +20,6 @@ from pathlib import Path
 
 import click
 from .rocrate import ROCrate
-from .model.preview import Preview
 from .model.computerlanguage import LANG_MAP
 from .model.testservice import SERVICE_MAP
 from .model.softwareapplication import APP_MAP
@@ -44,18 +43,21 @@ def cli(ctx, crate_dir):
 
 
 @cli.command()
+@click.option('--gen-preview', is_flag=True)
 @click.pass_obj
-def init(state):
+def init(state, gen_preview):
     crate_dir = state.crate_dir or os.getcwd()
-    crate = ROCrate(crate_dir, init=True, load_preview=True)
+    crate = ROCrate(crate_dir, init=True, gen_preview=gen_preview)
     crate.metadata.write(crate_dir)
+    if crate.preview:
+        crate.preview.write(crate_dir)
 
 
 @cli.group()
 @click.pass_obj
 def add(state):
     crate_dir = state.crate_dir or os.getcwd()
-    state.crate = ROCrate(crate_dir, init=False, load_preview=True)
+    state.crate = ROCrate(crate_dir, init=False, gen_preview=False)
 
 
 @add.command()
@@ -73,9 +75,6 @@ def workflow(state, path, language):
     # TODO: add command options for main and gen_cwl
     state.crate.add_workflow(source, dest_path, main=True, lang=language, gen_cwl=False)
     state.crate.metadata.write(crate_dir)
-    # FIXME: change preview generation to be optional when reading a crate
-    if not (Path(crate_dir) / Preview.BASENAME).is_file():
-        state.crate.preview.write(crate_dir)
 
 
 @add.command(name="test-suite")
diff --git a/rocrate/rocrate.py b/rocrate/rocrate.py
index 4470650..72cada4 100644
--- a/rocrate/rocrate.py
+++ b/rocrate/rocrate.py
@@ -49,7 +49,7 @@ from .utils import is_url
 
 class ROCrate():
 
-    def __init__(self, source_path=None, load_preview=False, init=False):
+    def __init__(self, source_path=None, gen_preview=False, init=False):
         self.__entity_map = {}
         self.default_entities = []
         self.data_entities = []
@@ -58,15 +58,19 @@ class ROCrate():
         # from zip
         self.uuid = uuid.uuid4()
         self.arcp_base_uri = f"arcp://uuid,{self.uuid}/"
+        self.preview = None
+
+        if gen_preview:
+            self.add(Preview(self))
 
         # TODO: default_properties must include name, description,
         # datePublished, license
         if not source_path:
             # create a new ro-crate
-            self.add(RootDataset(self), Metadata(self), Preview(self))
+            self.add(RootDataset(self), Metadata(self))
         elif init:
             # initialize an ro-crate from a directory tree
-            self.__init_from_tree(source_path, load_preview=load_preview)
+            self.__init_from_tree(source_path, gen_preview=gen_preview)
         else:
             # load an existing ro-crate
             if zipfile.is_zipfile(source_path):
@@ -85,18 +89,16 @@ class ROCrate():
                                  f'missing {Metadata.BASENAME}')
             self.add(MetadataClass(self))
             entities = self.entities_from_metadata(metadata_path)
-            self.build_crate(entities, source_path, load_preview)
+            self.build_crate(entities, source_path, gen_preview)
             # TODO: load root dataset properties
         # in the zip case, self.source_path is the extracted dir
         self.source_path = source_path
 
-    def __init_from_tree(self, top_dir, load_preview=False):
+    def __init_from_tree(self, top_dir, gen_preview=False):
         top_dir = Path(top_dir)
         if not top_dir.is_dir():
             raise ValueError(f"{top_dir} is not a valid directory path")
         self.add(RootDataset(self), Metadata(self))
-        if not load_preview:
-            self.add(Preview(self))
         for root, dirs, files in os.walk(top_dir):
             root = Path(root)
             for name in dirs:
@@ -108,7 +110,7 @@ class ROCrate():
                     continue
                 if source != top_dir / Preview.BASENAME:
                     self.add_file(source, source.relative_to(top_dir))
-                elif load_preview:
+                elif not gen_preview:
                     self.add(Preview(self, source))
 
     def entities_from_metadata(self, metadata_path):
@@ -165,7 +167,7 @@ class ROCrate():
             "see https://www.researchobject.org/ro-crate/1.1/root-data-entity.html"
         )
 
-    def build_crate(self, entities, source, load_preview):
+    def build_crate(self, entities, source, gen_preview):
         # add data and contextual entities to the crate
         (metadata_id, root_id) = self.find_root_entity_id(entities)
         root_entity = entities[root_id]
@@ -177,12 +179,9 @@ class ROCrate():
         root_entity.pop('hasPart', None)
         self.add(RootDataset(self, root_entity))
 
-        # check if a preview is present
-        if Preview.BASENAME in entities.keys() and load_preview:
+        if not gen_preview and Preview.BASENAME in entities:
             preview_source = os.path.join(source, Preview.BASENAME)
             self.add(Preview(self, preview_source))
-        else:
-            self.add(Preview(self))
 
         added_entities = []
         # iterate over data entities


Test patch:
diff --git a/test/test_cli.py b/test/test_cli.py
index 9c43ff9..da631ec 100644
--- a/test/test_cli.py
+++ b/test/test_cli.py
@@ -23,10 +23,11 @@ from rocrate.cli import cli
 from rocrate.model.metadata import TESTING_EXTRA_TERMS
 
 
-@pytest.mark.parametrize("cwd", [False, True])
-def test_cli_init(test_data_dir, helpers, monkeypatch, cwd):
+@pytest.mark.parametrize("gen_preview,cwd", [(False, False), (False, True), (True, False), (True, True)])
+def test_cli_init(test_data_dir, helpers, monkeypatch, cwd, gen_preview):
     crate_dir = test_data_dir / "ro-crate-galaxy-sortchangecase"
     metadata_path = crate_dir / helpers.METADATA_FILE_NAME
+    preview_path = crate_dir / helpers.PREVIEW_FILE_NAME
     metadata_path.unlink()
 
     runner = CliRunner()
@@ -36,9 +37,15 @@ def test_cli_init(test_data_dir, helpers, monkeypatch, cwd):
     else:
         args.extend(["-c", str(crate_dir)])
     args.append("init")
+    if gen_preview:
+        args.append("--gen-preview")
     result = runner.invoke(cli, args)
     assert result.exit_code == 0
     assert metadata_path.is_file()
+    if gen_preview:
+        assert preview_path.is_file()
+    else:
+        assert not preview_path.exists()
 
     json_entities = helpers.read_json_entities(crate_dir)
     assert "sort-and-change-case.ga" in json_entities
diff --git a/test/test_model.py b/test/test_model.py
index 36c2bbf..f1f0573 100644
--- a/test/test_model.py
+++ b/test/test_model.py
@@ -29,7 +29,7 @@ RAW_REPO_URL = "https://raw.githubusercontent.com/ResearchObject/ro-crate-py"
 
 
 def test_dereferencing(test_data_dir, helpers):
-    crate = ROCrate()
+    crate = ROCrate(gen_preview=True)
 
     # verify default entities
     root_dataset = crate.dereference('./')
diff --git a/test/test_read.py b/test/test_read.py
index eea335a..a3e334b 100644
--- a/test/test_read.py
+++ b/test/test_read.py
@@ -29,15 +29,15 @@ _URL = ('https://raw.githubusercontent.com/ResearchObject/ro-crate-py/master/'
         'test/test-data/sample_file.txt')
 
 
-@pytest.mark.parametrize("load_preview,from_zip", [(False, False), (True, False), (True, True)])
-def test_crate_dir_loading(test_data_dir, tmpdir, helpers, load_preview, from_zip):
+@pytest.mark.parametrize("gen_preview,from_zip", [(False, False), (True, False), (True, True)])
+def test_crate_dir_loading(test_data_dir, tmpdir, helpers, gen_preview, from_zip):
     # load crate
     crate_dir = test_data_dir / 'read_crate'
     if from_zip:
         zip_source = shutil.make_archive(tmpdir / "read_crate.crate", "zip", crate_dir)
-        crate = ROCrate(zip_source, load_preview=load_preview)
+        crate = ROCrate(zip_source, gen_preview=gen_preview)
     else:
-        crate = ROCrate(crate_dir, load_preview=load_preview)
+        crate = ROCrate(crate_dir, gen_preview=gen_preview)
 
     # check loaded entities and properties
     root = crate.dereference('./')
@@ -65,7 +65,7 @@ def test_crate_dir_loading(test_data_dir, tmpdir, helpers, load_preview, from_zi
     assert preview_prop['@id'] == preview.id
     assert preview_prop['@type'] == 'CreativeWork'
     assert preview_prop['about'] == {'@id': './'}
-    if load_preview:
+    if not gen_preview:
         assert Path(preview.source).name == helpers.PREVIEW_FILE_NAME
     else:
         assert not preview.source
@@ -127,7 +127,7 @@ def test_crate_dir_loading(test_data_dir, tmpdir, helpers, load_preview, from_zi
         assert f1.read() == f2.read()
     preview_path = out_path / helpers.PREVIEW_FILE_NAME
     assert preview_path.exists()
-    if load_preview:
+    if not gen_preview:
         with open(preview.source) as f1, open(preview_path) as f2:
             assert f1.read() == f2.read()
 
@@ -209,18 +209,16 @@ def test_init(test_data_dir, tmpdir, helpers, override):
             assert f1.read() == f2.read()
 
 
-@pytest.mark.parametrize("load_preview,preview_exists", [(False, False), (False, True), (True, False), (True, True)])
-def test_init_preview(test_data_dir, tmpdir, helpers, load_preview, preview_exists):
+@pytest.mark.parametrize("gen_preview,preview_exists", [(False, False), (False, True), (True, False), (True, True)])
+def test_init_preview(test_data_dir, tmpdir, helpers, gen_preview, preview_exists):
     crate_dir = test_data_dir / "ro-crate-galaxy-sortchangecase"
     dummy_prev_content = "foo\nbar\n"
     if preview_exists:
         with open(crate_dir / helpers.PREVIEW_FILE_NAME, "wt") as f:
             f.write(dummy_prev_content)
-    crate = ROCrate(crate_dir, load_preview=load_preview, init=True)
+    crate = ROCrate(crate_dir, gen_preview=gen_preview, init=True)
     prev = crate.dereference(helpers.PREVIEW_FILE_NAME)
-    if load_preview and not preview_exists:
-        assert prev is None
-    else:
+    if gen_preview or preview_exists:
         assert prev is not None
 
     out_path = tmpdir / 'ro_crate_out'
@@ -228,12 +226,13 @@ def test_init_preview(test_data_dir, tmpdir, helpers, load_preview, preview_exis
     crate.write_crate(out_path)
 
     out_prev_path = out_path / helpers.PREVIEW_FILE_NAME
-    if load_preview and not preview_exists:
-        assert not out_prev_path.exists()
-    else:
+    if gen_preview or preview_exists:
         assert out_prev_path.is_file()
-        if load_preview:
-            assert out_prev_path.open().read() == dummy_prev_content
+    else:
+        assert not out_prev_path.exists()
+
+    if not gen_preview and preview_exists:
+        assert out_prev_path.open().read() == dummy_prev_content
 
 
 def test_no_parts(tmpdir):
diff --git a/test/test_write.py b/test/test_write.py
index fb99fb9..9c73ef4 100644
--- a/test/test_write.py
+++ b/test/test_write.py
@@ -27,9 +27,9 @@ from rocrate.model.person import Person
 from rocrate.rocrate import ROCrate
 
 
-@pytest.mark.parametrize("to_zip", [False, True])
-def test_file_writing(test_data_dir, tmpdir, helpers, to_zip):
-    crate = ROCrate()
+@pytest.mark.parametrize("gen_preview,to_zip", [(False, False), (False, True), (True, False), (True, True)])
+def test_file_writing(test_data_dir, tmpdir, helpers, gen_preview, to_zip):
+    crate = ROCrate(gen_preview=gen_preview)
     crate_name = 'Test crate'
     crate.name = crate_name
     creator_id = '001'
@@ -66,7 +66,10 @@ def test_file_writing(test_data_dir, tmpdir, helpers, to_zip):
     metadata_path = out_path / helpers.METADATA_FILE_NAME
     assert metadata_path.exists()
     preview_path = out_path / helpers.PREVIEW_FILE_NAME
-    assert preview_path.exists()
+    if gen_preview:
+        assert preview_path.exists()
+    else:
+        assert not preview_path.exists()
     file1 = out_path / sample_file_id
     file2 = out_path / sample_file2_id
     file_subdir = out_path / test_dir_id / file_subdir_id
@@ -90,10 +93,8 @@ def test_file_writing(test_data_dir, tmpdir, helpers, to_zip):
     assert root["creator"] == {"@id": formatted_creator_id}
     assert formatted_creator_id in json_entities
     assert json_entities[formatted_creator_id]["name"] == creator_name
-    assert helpers.PREVIEW_FILE_NAME in json_entities
-    preview = json_entities[helpers.PREVIEW_FILE_NAME]
-    assert preview["@type"] == "CreativeWork"
-    assert preview["about"] == {"@id": "./"}
+    if gen_preview:
+        assert helpers.PREVIEW_FILE_NAME in json_entities
 
 
 def test_file_stringio(tmpdir, helpers):