From d1989b1a44ec74d81ded7b0bed488f890043b05f Mon Sep 17 00:00:00 2001
From: alaskowski <alaskowski@ethz.ch>
Date: Fri, 24 Feb 2023 13:03:56 +0100
Subject: [PATCH] SSDM-13330: Added upload of files to a new dataset flow for
 PHYSICAL data.

---
 .../src/python/obis/dm/commands/upload.py     | 46 +++++++++++++++++++
 .../src/python/obis/dm/data_mgmt.py           | 21 +++++++++
 .../src/python/obis/scripts/cli.py            | 33 +++++++++++--
 3 files changed, 97 insertions(+), 3 deletions(-)
 create mode 100644 app-openbis-command-line/src/python/obis/dm/commands/upload.py

diff --git a/app-openbis-command-line/src/python/obis/dm/commands/upload.py b/app-openbis-command-line/src/python/obis/dm/commands/upload.py
new file mode 100644
index 00000000000..d9ee708b584
--- /dev/null
+++ b/app-openbis-command-line/src/python/obis/dm/commands/upload.py
@@ -0,0 +1,46 @@
+#   Copyright ETH 2023 Zürich, Scientific IT Services
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+
+from .openbis_command import OpenbisCommand
+from ..command_result import CommandResult
+from ..utils import cd
+from ...scripts.click_util import click_echo
+
+
+class Upload(OpenbisCommand):
+    """
+    Command to upload physical files to form a data set.
+    """
+
+    def __init__(self, dm, sample_id, data_set_type, files):
+        """
+        :param dm: data management
+        :param sample_id: permId or sample path of the parent sample
+        :param data_set_type: type of newly created data set.
+        :param files: list of files/directories to upload
+        """
+        self.data_set_type = data_set_type
+        self.files = files
+        self.sample_id = sample_id
+        self.load_global_config(dm)
+        super(Upload, self).__init__(dm)
+
+    def run(self):
+        with cd(self.data_mgmt.invocation_path):
+            click_echo(f"Uploading files {self.files} under {self.sample_id}")
+            ds = self.openbis.new_dataset(type=self.data_set_type, sample=self.sample_id,
+                                          files=self.files)
+            result = ds.save()
+            return CommandResult(returncode=0, output=f"Upload finished. New dataset: {result}")
diff --git a/app-openbis-command-line/src/python/obis/dm/data_mgmt.py b/app-openbis-command-line/src/python/obis/dm/data_mgmt.py
index 93ed3746e1c..326d8bda283 100644
--- a/app-openbis-command-line/src/python/obis/dm/data_mgmt.py
+++ b/app-openbis-command-line/src/python/obis/dm/data_mgmt.py
@@ -35,6 +35,7 @@ from .commands.move import Move
 from .commands.openbis_sync import OpenbisSync
 from .commands.removeref import Removeref
 from .commands.search import Search
+from .commands.upload import Upload
 from .git import GitWrapper
 from .utils import Type
 from .utils import cd
@@ -217,6 +218,15 @@ class AbstractDataMgmt(metaclass=abc.ABCMeta):
         """
         return
 
+    @abc.abstractmethod
+    def upload(self, sample_id, data_set_type, files):
+        """Upload files/directories into a new data set.
+        :param sample_id: permId or sample path of the parent sample
+        :param data_set_type: type of created data set
+        :param files: list of files/directories to upload
+        """
+        return
+
     @abc.abstractmethod
     def search_object(self, type_code, space, project, experiment, property_code, property_value,
                       save):
@@ -231,6 +241,7 @@ class AbstractDataMgmt(metaclass=abc.ABCMeta):
         """
         return
 
+    @abc.abstractmethod
     def search_data_set(self, type_code, space, project, experiment, property_code, property_value,
                         save):
         """Search for datasets in openBIS using filtering criteria.
@@ -290,6 +301,9 @@ class NoGitDataMgmt(AbstractDataMgmt):
     def search_data_set(self, *_):
         self.error_raise("search", "No git command found.")
 
+    def upload(self, *_):
+        self.error_raise("upload", "No git command found.")
+
 
 def restore_signal_handler(data_mgmt):
     data_mgmt.restore()
@@ -575,6 +589,9 @@ class GitDataMgmt(AbstractDataMgmt):
     def search_data_set(self, *_):
         self.error_raise("search", "This functionality is not implemented for data of LINK type.")
 
+    def upload(self, *_):
+        self.error_raise("upload", "This functionality is not implemented for data of LINK type.")
+
 
 class PhysicalDataMgmt(AbstractDataMgmt):
     """DataMgmt operations for DSS-stored data."""
@@ -624,6 +641,10 @@ class PhysicalDataMgmt(AbstractDataMgmt):
         cmd = DownloadPhysical(self, data_set_id, file)
         return cmd.run()
 
+    def upload(self, sample_id, data_set_type, files):
+        cmd = Upload(self, sample_id, data_set_type, files)
+        return cmd.run()
+
     def search_object(self, type_code, space, project, experiment, property_code, property_value,
                       save):
         cmd = Search(self, type_code, space, project, experiment, property_code, property_value,
diff --git a/app-openbis-command-line/src/python/obis/scripts/cli.py b/app-openbis-command-line/src/python/obis/scripts/cli.py
index b081071c8e1..db38e2935f4 100644
--- a/app-openbis-command-line/src/python/obis/scripts/cli.py
+++ b/app-openbis-command-line/src/python/obis/scripts/cli.py
@@ -748,7 +748,7 @@ def removeref(ctx, data_set_id, repository):
                repository=repository)
 
 
-# data set commands: download / clone
+# data set commands: download, upload, clone
 
 # download
 
@@ -763,7 +763,7 @@ _download_params = [
 ]
 
 
-@data_set.command("download", short_help="Download files of a linked data set.")
+@data_set.command("download", short_help="Download files of a data set.")
 @add_params(_download_params)
 @click.pass_context
 def data_set_download(ctx, content_copy_index, file, data_set_id, skip_integrity_check):
@@ -772,7 +772,7 @@ def data_set_download(ctx, content_copy_index, file, data_set_id, skip_integrity
                                                         skip_integrity_check))
 
 
-@cli.command(short_help="Download files of a linked data set.")
+@cli.command("download", short_help="Download files of a data set.")
 @add_params(_download_params)
 @click.pass_context
 def download(ctx, content_copy_index, file, data_set_id, skip_integrity_check):
@@ -781,6 +781,33 @@ def download(ctx, content_copy_index, file, data_set_id, skip_integrity_check):
                data_set_id=data_set_id, skip_integrity_check=skip_integrity_check)
 
 
+# upload
+
+
+_upload_params = [
+    click.option(
+        '-f', '--file', "files", help='file or directory to upload.', required=True, multiple=True),
+    click.argument('sample_id'),
+    click.argument('data_set_type'),
+]
+
+
+@data_set.command("upload", short_help="Upload files to form a data set.")
+@add_params(_upload_params)
+@click.pass_context
+def data_set_upload(ctx, sample_id, data_set_type, files):
+    return ctx.obj['runner'].run("upload",
+                                 lambda dm: dm.upload(sample_id, data_set_type, files))
+
+
+@cli.command("upload", short_help="Upload files to form a data set.")
+@add_params(_upload_params)
+@click.pass_context
+def download(ctx, sample_id, data_set_type, files):
+    ctx.obj['runner'] = DataMgmtRunner(ctx.obj, halt_on_error_log=False)
+    ctx.invoke(data_set_upload, files=files, sample_id=sample_id, data_set_type=data_set_type)
+
+
 # clone
 
 
-- 
GitLab